aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--botan_version.py2
-rw-r--r--checks/bench.cpp36
-rw-r--r--checks/common.h4
-rw-r--r--checks/cvc_tests.cpp54
-rw-r--r--checks/dolook.cpp30
-rw-r--r--checks/ec_tests.cpp122
-rw-r--r--checks/ecdh.cpp4
-rw-r--r--checks/ecdsa.cpp54
-rw-r--r--checks/pk.cpp76
-rw-r--r--checks/pk_bench.cpp42
-rw-r--r--checks/timer.cpp5
-rw-r--r--checks/validate.cpp18
-rw-r--r--checks/validate.dat55
-rw-r--r--checks/x509.cpp3
-rwxr-xr-xconfigure.py88
-rw-r--r--doc/contents.txt3
-rw-r--r--doc/examples/GNUmakefile9
-rw-r--r--doc/examples/asio_tls_server.cpp295
-rw-r--r--doc/examples/asn1.cpp14
-rw-r--r--doc/examples/bench.cpp17
-rw-r--r--doc/examples/benchmark.cpp5
-rw-r--r--doc/examples/bzip.cpp15
-rw-r--r--doc/examples/ca.cpp11
-rw-r--r--doc/examples/cms_dec.cpp120
-rw-r--r--doc/examples/cms_enc.cpp59
-rw-r--r--doc/examples/credentials.h284
-rw-r--r--doc/examples/decrypt.cpp6
-rw-r--r--doc/examples/dh.cpp4
-rw-r--r--doc/examples/dsa_ver.cpp4
-rw-r--r--doc/examples/ecdsa.cpp2
-rw-r--r--doc/examples/encrypt.cpp6
-rw-r--r--doc/examples/encrypt2.cpp10
-rw-r--r--doc/examples/fpe.cpp6
-rw-r--r--doc/examples/gen_certs.cpp10
-rw-r--r--doc/examples/hash_quickly.cpp2
-rw-r--r--doc/examples/keywrap.cpp4
-rw-r--r--doc/examples/new_engine.cpp2
-rw-r--r--doc/examples/pqg_gen.cpp6
-rw-r--r--doc/examples/read_ssh.cpp2
-rw-r--r--doc/examples/rng_test.cpp8
-rw-r--r--doc/examples/row_encryptor.cpp20
-rw-r--r--doc/examples/rsa_dec.cpp10
-rw-r--r--doc/examples/rsa_enc.cpp14
-rw-r--r--doc/examples/rsa_manykey.cpp2
-rw-r--r--doc/examples/self_sig.cpp3
-rw-r--r--doc/examples/socket.h20
-rw-r--r--doc/examples/tls_client.cpp253
-rw-r--r--doc/examples/tls_server.cpp200
-rw-r--r--doc/examples/tss.cpp2
-rw-r--r--doc/index.txt2
-rw-r--r--doc/log.txt14
-rw-r--r--doc/ssl.txt58
-rw-r--r--doc/tls.txt151
-rw-r--r--src/algo_base/algo_base.h7
-rw-r--r--src/algo_base/buf_comp.h32
-rw-r--r--src/algo_base/symkey.cpp16
-rw-r--r--src/algo_base/symkey.h37
-rw-r--r--src/algo_factory/algo_cache.h58
-rw-r--r--src/algo_factory/algo_factory.cpp21
-rw-r--r--src/algo_factory/algo_factory.h3
-rw-r--r--src/algo_factory/info.txt1
-rw-r--r--src/alloc/alloc_mmap/info.txt28
-rw-r--r--src/alloc/alloc_mmap/mmap_mem.cpp143
-rw-r--r--src/alloc/alloc_mmap/mmap_mem.h36
-rw-r--r--src/alloc/allocate.h65
-rw-r--r--src/alloc/info.txt1
-rw-r--r--src/alloc/locking_allocator/info.txt1
-rw-r--r--src/alloc/locking_allocator/locking_allocator.cpp236
-rw-r--r--src/alloc/locking_allocator/locking_allocator.h39
-rw-r--r--src/alloc/mem_pool/info.txt12
-rw-r--r--src/alloc/mem_pool/mem_pool.cpp252
-rw-r--r--src/alloc/mem_pool/mem_pool.h77
-rw-r--r--src/alloc/secmem.h439
-rw-r--r--src/alloc/system_alloc/defalloc.cpp103
-rw-r--r--src/alloc/system_alloc/defalloc.h46
-rw-r--r--src/alloc/system_alloc/info.txt13
-rw-r--r--src/asn1/alg_id.cpp4
-rw-r--r--src/asn1/alg_id.h6
-rw-r--r--src/asn1/asn1_alt.cpp27
-rw-r--r--src/asn1/asn1_att.cpp4
-rw-r--r--src/asn1/asn1_int.cpp8
-rw-r--r--src/asn1/asn1_int.h4
-rw-r--r--src/asn1/asn1_obj.h9
-rw-r--r--src/asn1/asn1_oid.cpp4
-rw-r--r--src/asn1/asn1_str.cpp2
-rw-r--r--src/asn1/asn1_tm.cpp54
-rw-r--r--src/asn1/ber_dec.cpp122
-rw-r--r--src/asn1/ber_dec.h85
-rw-r--r--src/asn1/der_enc.cpp73
-rw-r--r--src/asn1/der_enc.h37
-rw-r--r--src/asn1/x509_dn.cpp74
-rw-r--r--src/asn1/x509_dn.h4
-rw-r--r--src/benchmark/benchmark.cpp77
-rw-r--r--src/benchmark/benchmark.h5
-rw-r--r--src/block/aes/aes.cpp21
-rw-r--r--src/block/aes/aes.h18
-rw-r--r--src/block/aes_ni/aes_ni.h6
-rw-r--r--src/block/aes_ssse3/aes_ssse3.cpp11
-rw-r--r--src/block/aes_ssse3/aes_ssse3.h12
-rw-r--r--src/block/block_cipher.h44
-rw-r--r--src/block/blowfish/blowfish.cpp19
-rw-r--r--src/block/blowfish/blowfish.h7
-rw-r--r--src/block/camellia/camellia.cpp168
-rw-r--r--src/block/camellia/camellia.h46
-rw-r--r--src/block/camellia/camellia_sbox.h545
-rw-r--r--src/block/camellia/info.txt8
-rw-r--r--src/block/cast/cast128.cpp30
-rw-r--r--src/block/cast/cast128.h10
-rw-r--r--src/block/cast/cast256.cpp61
-rw-r--r--src/block/cast/cast256.h8
-rw-r--r--src/block/des/des.cpp2
-rw-r--r--src/block/des/des.h10
-rw-r--r--src/block/des/desx.cpp4
-rw-r--r--src/block/des/desx.h6
-rw-r--r--src/block/gost_28147/gost_28147.cpp4
-rw-r--r--src/block/gost_28147/gost_28147.h13
-rw-r--r--src/block/idea/idea.cpp3
-rw-r--r--src/block/idea/idea.h11
-rw-r--r--src/block/kasumi/kasumi.cpp4
-rw-r--r--src/block/kasumi/kasumi.h6
-rw-r--r--src/block/lion/lion.cpp14
-rw-r--r--src/block/lion/lion.h2
-rw-r--r--src/block/lubyrack/lubyrack.cpp14
-rw-r--r--src/block/lubyrack/lubyrack.h2
-rw-r--r--src/block/mars/mars.cpp4
-rw-r--r--src/block/mars/mars.h6
-rw-r--r--src/block/misty1/misty1.cpp9
-rw-r--r--src/block/misty1/misty1.h4
-rw-r--r--src/block/noekeon/noekeon.cpp6
-rw-r--r--src/block/noekeon/noekeon.h8
-rw-r--r--src/block/noekeon_simd/noekeon_simd.cpp4
-rw-r--r--src/block/rc2/rc2.cpp5
-rw-r--r--src/block/rc2/rc2.h6
-rw-r--r--src/block/rc5/rc5.cpp16
-rw-r--r--src/block/rc5/rc5.h9
-rw-r--r--src/block/rc6/rc6.cpp4
-rw-r--r--src/block/rc6/rc6.h6
-rw-r--r--src/block/safer/safer_sk.cpp18
-rw-r--r--src/block/safer/safer_sk.h6
-rw-r--r--src/block/seed/seed.cpp4
-rw-r--r--src/block/seed/seed.h6
-rw-r--r--src/block/serpent/serpent.cpp5
-rw-r--r--src/block/serpent/serpent.h8
-rw-r--r--src/block/serpent_x86_32/serp_x86_32.cpp2
-rw-r--r--src/block/skipjack/skipjack.cpp3
-rw-r--r--src/block/skipjack/skipjack.h4
-rw-r--r--src/block/square/square.cpp19
-rw-r--r--src/block/square/square.h6
-rw-r--r--src/block/tea/tea.cpp1
-rw-r--r--src/block/tea/tea.h6
-rw-r--r--src/block/twofish/twofish.cpp9
-rw-r--r--src/block/twofish/twofish.h4
-rw-r--r--src/block/xtea/xtea.cpp4
-rw-r--r--src/block/xtea/xtea.h8
-rw-r--r--src/build-data/buildh.in2
-rw-r--r--src/build-data/cc/clang.txt16
-rw-r--r--src/build-data/cc/compaq.txt26
-rw-r--r--src/build-data/cc/gcc.txt20
-rw-r--r--src/build-data/cc/icc.txt4
-rw-r--r--src/build-data/cc/kai.txt27
-rw-r--r--src/build-data/cc/mipspro.txt39
-rw-r--r--src/build-data/cc/sgipro64.txt27
-rw-r--r--src/build-data/os/windows.txt5
-rw-r--r--src/cert/cvc/asn1_eac_tm.cpp122
-rw-r--r--src/cert/cvc/cvc_ado.cpp22
-rw-r--r--src/cert/cvc/cvc_ado.h8
-rw-r--r--src/cert/cvc/cvc_cert.cpp16
-rw-r--r--src/cert/cvc/cvc_cert.h4
-rw-r--r--src/cert/cvc/cvc_gen_cert.h28
-rw-r--r--src/cert/cvc/cvc_req.cpp2
-rw-r--r--src/cert/cvc/cvc_req.h2
-rw-r--r--src/cert/cvc/cvc_self.cpp54
-rw-r--r--src/cert/cvc/eac_asn_obj.h64
-rw-r--r--src/cert/cvc/eac_obj.h2
-rw-r--r--src/cert/cvc/ecdsa_sig.cpp14
-rw-r--r--src/cert/cvc/ecdsa_sig.h8
-rw-r--r--src/cert/cvc/info.txt1
-rw-r--r--src/cert/cvc/signed_obj.cpp6
-rw-r--r--src/cert/cvc/signed_obj.h10
-rw-r--r--src/cert/x509/certstor.cpp8
-rw-r--r--src/cert/x509/certstor.h8
-rw-r--r--src/cert/x509/crl_ent.cpp3
-rw-r--r--src/cert/x509/crl_ent.h4
-rw-r--r--src/cert/x509/pkcs10.cpp17
-rw-r--r--src/cert/x509/pkcs10.h8
-rw-r--r--src/cert/x509/x509_ca.cpp99
-rw-r--r--src/cert/x509/x509_ca.h8
-rw-r--r--src/cert/x509/x509_crl.cpp10
-rw-r--r--src/cert/x509/x509_crl.h12
-rw-r--r--src/cert/x509/x509_ext.cpp62
-rw-r--r--src/cert/x509/x509_ext.h52
-rw-r--r--src/cert/x509/x509_obj.cpp30
-rw-r--r--src/cert/x509/x509_obj.h18
-rw-r--r--src/cert/x509/x509cert.cpp141
-rw-r--r--src/cert/x509/x509cert.h21
-rw-r--r--src/cert/x509/x509opt.cpp8
-rw-r--r--src/cert/x509/x509path.cpp2
-rw-r--r--src/cert/x509/x509path.h5
-rw-r--r--src/cert/x509/x509self.cpp23
-rw-r--r--src/cms/cms_algo.cpp14
-rw-r--r--src/cms/cms_comp.cpp4
-rw-r--r--src/cms/cms_dalg.cpp17
-rw-r--r--src/cms/cms_dec.h2
-rw-r--r--src/cms/cms_ealg.cpp18
-rw-r--r--src/cms/cms_enc.cpp4
-rw-r--r--src/cms/cms_enc.h12
-rw-r--r--src/codec/base64/base64.cpp11
-rw-r--r--src/codec/base64/base64.h10
-rw-r--r--src/codec/hex/hex.cpp12
-rw-r--r--src/codec/hex/hex.h14
-rw-r--r--src/codec/openpgp/openpgp.cpp6
-rw-r--r--src/codec/openpgp/openpgp.h4
-rw-r--r--src/codec/pem/pem.cpp30
-rw-r--r--src/codec/pem/pem.h71
-rw-r--r--src/constructs/aont/package.cpp16
-rw-r--r--src/constructs/cryptobox/cryptobox.cpp14
-rw-r--r--src/constructs/fpe_fe1/fpe_fe1.cpp18
-rw-r--r--src/constructs/fpe_fe1/fpe_fe1.h4
-rw-r--r--src/constructs/rfc3394/rfc3394.cpp24
-rw-r--r--src/constructs/rfc3394/rfc3394.h4
-rw-r--r--src/constructs/srp6/srp6.cpp81
-rw-r--r--src/constructs/srp6/srp6.h71
-rw-r--r--src/constructs/srp6/srp6_files.cpp4
-rw-r--r--src/constructs/srp6/srp6_files.h8
-rw-r--r--src/constructs/tss/tss.cpp12
-rw-r--r--src/constructs/tss/tss.h4
-rw-r--r--src/credentials/credentials_manager.cpp149
-rw-r--r--src/credentials/credentials_manager.h153
-rw-r--r--src/credentials/info.txt6
-rw-r--r--src/engine/asm_engine/asm_engine.cpp4
-rw-r--r--src/engine/asm_engine/asm_engine.h2
-rw-r--r--src/engine/core_engine/core_engine.h4
-rw-r--r--src/engine/core_engine/core_modes.cpp14
-rw-r--r--src/engine/core_engine/def_pk_ops.cpp10
-rw-r--r--src/engine/core_engine/lookup_block.cpp12
-rw-r--r--src/engine/core_engine/lookup_hash.cpp4
-rw-r--r--src/engine/core_engine/lookup_mac.cpp2
-rw-r--r--src/engine/core_engine/lookup_pbkdf.cpp2
-rw-r--r--src/engine/core_engine/lookup_stream.cpp2
-rw-r--r--src/engine/dyn_engine/dyn_engine.cpp6
-rw-r--r--src/engine/engine.cpp24
-rw-r--r--src/engine/gnump/gmp_wrap.h2
-rw-r--r--src/engine/gnump/gnump_pk.cpp16
-rw-r--r--src/engine/openssl/bn_wrap.cpp4
-rw-r--r--src/engine/openssl/bn_wrap.h2
-rw-r--r--src/engine/openssl/ossl_arc4.cpp4
-rw-r--r--src/engine/openssl/ossl_bc.cpp2
-rw-r--r--src/engine/openssl/ossl_pk.cpp16
-rw-r--r--src/engine/simd_engine/simd_engine.cpp4
-rw-r--r--src/engine/simd_engine/simd_engine.h2
-rw-r--r--src/entropy/cryptoapi_rng/es_capi.cpp2
-rw-r--r--src/entropy/dev_random/dev_random.cpp4
-rw-r--r--src/entropy/egd/es_egd.cpp2
-rw-r--r--src/entropy/entropy_src.h4
-rw-r--r--src/entropy/hres_timer/hres_timer.cpp6
-rw-r--r--src/entropy/proc_walk/es_ftw.cpp22
-rw-r--r--src/entropy/rdrand/info.txt20
-rw-r--r--src/entropy/rdrand/rdrand.cpp60
-rw-r--r--src/entropy/rdrand/rdrand.h28
-rw-r--r--src/entropy/unix_procs/es_unix.cpp4
-rw-r--r--src/entropy/unix_procs/unix_cmd.cpp22
-rw-r--r--src/filters/algo_filt.cpp4
-rw-r--r--src/filters/basefilt.h5
-rw-r--r--src/filters/buf_filt.h8
-rw-r--r--src/filters/bzip2/bzip2.cpp2
-rw-r--r--src/filters/bzip2/bzip2.h4
-rw-r--r--src/filters/codec_filt/b64_filt.cpp4
-rw-r--r--src/filters/codec_filt/b64_filt.h4
-rw-r--r--src/filters/codec_filt/hex_filt.cpp4
-rw-r--r--src/filters/codec_filt/hex_filt.h4
-rw-r--r--src/filters/data_snk.cpp2
-rw-r--r--src/filters/data_snk.h6
-rw-r--r--src/filters/data_src.cpp26
-rw-r--r--src/filters/data_src.h22
-rw-r--r--src/filters/fd_unix/fd_unix.cpp4
-rw-r--r--src/filters/filter.cpp4
-rw-r--r--src/filters/filter.h27
-rw-r--r--src/filters/filters.h2
-rw-r--r--src/filters/modes/cbc/cbc.cpp18
-rw-r--r--src/filters/modes/cbc/cbc.h4
-rw-r--r--src/filters/modes/cfb/cfb.cpp22
-rw-r--r--src/filters/modes/cfb/cfb.h4
-rw-r--r--src/filters/modes/cts/cts.cpp26
-rw-r--r--src/filters/modes/cts/cts.h4
-rw-r--r--src/filters/modes/eax/eax.cpp8
-rw-r--r--src/filters/modes/eax/eax.h8
-rw-r--r--src/filters/modes/eax/eax_dec.cpp10
-rw-r--r--src/filters/modes/ecb/ecb.cpp8
-rw-r--r--src/filters/modes/ecb/ecb.h4
-rw-r--r--src/filters/modes/xts/xts.cpp42
-rw-r--r--src/filters/modes/xts/xts.h4
-rw-r--r--src/filters/out_buf.cpp4
-rw-r--r--src/filters/pipe.cpp26
-rw-r--r--src/filters/pipe.h43
-rw-r--r--src/filters/pipe_io.cpp4
-rw-r--r--src/filters/pipe_rw.cpp16
-rw-r--r--src/filters/pk_filts/pk_filts.cpp9
-rw-r--r--src/filters/pk_filts/pk_filts.h10
-rw-r--r--src/filters/secqueue.cpp17
-rw-r--r--src/filters/secqueue.h2
-rw-r--r--src/filters/zlib/zlib.cpp33
-rw-r--r--src/filters/zlib/zlib.h20
-rw-r--r--src/hash/bmw_512/bmw_512.h2
-rw-r--r--src/hash/comb4p/comb4p.cpp10
-rw-r--r--src/hash/gost_3411/gost_3411.cpp10
-rw-r--r--src/hash/gost_3411/gost_3411.h2
-rw-r--r--src/hash/has160/has160.h2
-rw-r--r--src/hash/keccak/keccak.cpp8
-rw-r--r--src/hash/keccak/keccak.h2
-rw-r--r--src/hash/md2/md2.cpp6
-rw-r--r--src/hash/md2/md2.h2
-rw-r--r--src/hash/md4/md4.h4
-rw-r--r--src/hash/md5/md5.h4
-rw-r--r--src/hash/mdx_hash/mdx_hash.cpp4
-rw-r--r--src/hash/mdx_hash/mdx_hash.h2
-rw-r--r--src/hash/par_hash/par_hash.cpp51
-rw-r--r--src/hash/rmd128/rmd128.h2
-rw-r--r--src/hash/rmd160/rmd160.h2
-rw-r--r--src/hash/sha1/sha160.h4
-rw-r--r--src/hash/sha2_32/sha2_32.cpp2
-rw-r--r--src/hash/sha2_32/sha2_32.h4
-rw-r--r--src/hash/sha2_64/sha2_64.cpp2
-rw-r--r--src/hash/sha2_64/sha2_64.h4
-rw-r--r--src/hash/skein/skein_512.cpp23
-rw-r--r--src/hash/skein/skein_512.h6
-rw-r--r--src/hash/tiger/tiger.cpp11
-rw-r--r--src/hash/tiger/tiger.h4
-rw-r--r--src/hash/whirlpool/whrlpool.h2
-rw-r--r--src/kdf/kdf.cpp23
-rw-r--r--src/kdf/kdf.h26
-rw-r--r--src/kdf/kdf1/kdf1.cpp2
-rw-r--r--src/kdf/kdf1/kdf1.h2
-rw-r--r--src/kdf/kdf2/kdf2.cpp6
-rw-r--r--src/kdf/kdf2/kdf2.h2
-rw-r--r--src/kdf/mgf1/mgf1.cpp2
-rw-r--r--src/kdf/prf_ssl3/prf_ssl3.cpp6
-rw-r--r--src/kdf/prf_ssl3/prf_ssl3.h2
-rw-r--r--src/kdf/prf_tls/info.txt1
-rw-r--r--src/kdf/prf_tls/prf_tls.cpp25
-rw-r--r--src/kdf/prf_tls/prf_tls.h4
-rw-r--r--src/kdf/prf_x942/prf_x942.cpp10
-rw-r--r--src/kdf/prf_x942/prf_x942.h2
-rw-r--r--src/libstate/get_enc.cpp24
-rw-r--r--src/libstate/global_rng.cpp31
-rw-r--r--src/libstate/global_state.cpp6
-rw-r--r--src/libstate/info.txt3
-rw-r--r--src/libstate/init.cpp39
-rw-r--r--src/libstate/libstate.cpp148
-rw-r--r--src/libstate/libstate.h56
-rw-r--r--src/libstate/lookup.h8
-rw-r--r--src/libstate/policy.cpp84
-rw-r--r--src/mac/cbc_mac/cbc_mac.h2
-rw-r--r--src/mac/cmac/cmac.cpp8
-rw-r--r--src/mac/cmac/cmac.h6
-rw-r--r--src/mac/hmac/hmac.cpp13
-rw-r--r--src/mac/hmac/hmac.h4
-rw-r--r--src/mac/mac.cpp2
-rw-r--r--src/mac/ssl3mac/ssl3_mac.cpp24
-rw-r--r--src/mac/ssl3mac/ssl3_mac.h2
-rw-r--r--src/mac/x919_mac/x919_mac.cpp2
-rw-r--r--src/mac/x919_mac/x919_mac.h2
-rw-r--r--src/math/bigint/big_code.cpp38
-rw-r--r--src/math/bigint/big_io.cpp2
-rw-r--r--src/math/bigint/big_ops2.cpp40
-rw-r--r--src/math/bigint/big_ops3.cpp28
-rw-r--r--src/math/bigint/big_rand.cpp2
-rw-r--r--src/math/bigint/bigint.cpp37
-rw-r--r--src/math/bigint/bigint.h93
-rw-r--r--src/math/ec_gfp/point_gfp.cpp20
-rw-r--r--src/math/ec_gfp/point_gfp.h38
-rw-r--r--src/math/numbertheory/dsa_gen.cpp29
-rw-r--r--src/math/numbertheory/make_prm.cpp6
-rw-r--r--src/math/numbertheory/mp_numth.cpp10
-rw-r--r--src/math/numbertheory/numthry.cpp2
-rw-r--r--src/math/numbertheory/numthry.h4
-rw-r--r--src/math/numbertheory/pow_mod.cpp8
-rw-r--r--src/math/numbertheory/pow_mod.h2
-rw-r--r--src/math/numbertheory/powm_mnt.cpp8
-rw-r--r--src/mutex/info.txt5
-rw-r--r--src/mutex/mutex.h71
-rw-r--r--src/mutex/noop_mutex/info.txt9
-rw-r--r--src/mutex/noop_mutex/mux_noop.cpp50
-rw-r--r--src/mutex/noop_mutex/mux_noop.h26
-rw-r--r--src/mutex/pthreads/info.txt29
-rw-r--r--src/mutex/pthreads/mux_pthr.cpp58
-rw-r--r--src/mutex/pthreads/mux_pthr.h26
-rw-r--r--src/mutex/qt_mutex/info.txt17
-rw-r--r--src/mutex/qt_mutex/mux_qt.cpp35
-rw-r--r--src/mutex/qt_mutex/mux_qt.h27
-rw-r--r--src/mutex/win32_crit_section/info.txt15
-rw-r--r--src/mutex/win32_crit_section/mux_win32.cpp34
-rw-r--r--src/mutex/win32_crit_section/mux_win32.h26
-rw-r--r--src/passhash/bcrypt/bcrypt.cpp23
-rw-r--r--src/passhash/passhash9/passhash9.cpp15
-rw-r--r--src/pbe/pbe.h2
-rw-r--r--src/pbe/pbes1/pbes1.cpp8
-rw-r--r--src/pbe/pbes1/pbes1.h4
-rw-r--r--src/pbe/pbes2/pbes2.cpp14
-rw-r--r--src/pbe/pbes2/pbes2.h4
-rw-r--r--src/pbkdf/pbkdf1/pbkdf1.cpp2
-rw-r--r--src/pbkdf/pbkdf2/pbkdf2.cpp10
-rw-r--r--src/pbkdf/pgps2k/pgp_s2k.cpp4
-rw-r--r--src/pk_pad/eme.cpp8
-rw-r--r--src/pk_pad/eme.h12
-rw-r--r--src/pk_pad/eme1/eme1.cpp17
-rw-r--r--src/pk_pad/eme1/eme1.h6
-rw-r--r--src/pk_pad/eme_pkcs/eme_pkcs.cpp10
-rw-r--r--src/pk_pad/eme_pkcs/eme_pkcs.h4
-rw-r--r--src/pk_pad/emsa.h8
-rw-r--r--src/pk_pad/emsa1/emsa1.cpp14
-rw-r--r--src/pk_pad/emsa1/emsa1.h6
-rw-r--r--src/pk_pad/emsa1_bsi/emsa1_bsi.cpp2
-rw-r--r--src/pk_pad/emsa1_bsi/emsa1_bsi.h2
-rw-r--r--src/pk_pad/emsa2/emsa2.cpp16
-rw-r--r--src/pk_pad/emsa2/emsa2.h8
-rw-r--r--src/pk_pad/emsa3/emsa3.cpp30
-rw-r--r--src/pk_pad/emsa3/emsa3.h16
-rw-r--r--src/pk_pad/emsa4/emsa4.cpp52
-rw-r--r--src/pk_pad/emsa4/emsa4.h6
-rw-r--r--src/pk_pad/emsa_raw/emsa_raw.cpp10
-rw-r--r--src/pk_pad/emsa_raw/emsa_raw.h8
-rw-r--r--src/pk_pad/hash_id/hash_id.cpp43
-rw-r--r--src/pk_pad/hash_id/hash_id.h2
-rw-r--r--src/pubkey/dh/dh.cpp10
-rw-r--r--src/pubkey/dh/dh.h10
-rw-r--r--src/pubkey/dl_algo/dl_algo.cpp10
-rw-r--r--src/pubkey/dl_algo/dl_algo.h8
-rw-r--r--src/pubkey/dl_group/dl_group.cpp22
-rw-r--r--src/pubkey/dl_group/dl_group.h5
-rw-r--r--src/pubkey/dlies/dlies.cpp31
-rw-r--r--src/pubkey/dlies/dlies.h13
-rw-r--r--src/pubkey/dsa/dsa.cpp26
-rw-r--r--src/pubkey/dsa/dsa.h6
-rw-r--r--src/pubkey/ec_group/ec_group.cpp18
-rw-r--r--src/pubkey/ec_group/ec_group.h8
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp10
-rw-r--r--src/pubkey/ecc_key/ecc_key.h10
-rw-r--r--src/pubkey/ecdh/ecdh.cpp2
-rw-r--r--src/pubkey/ecdh/ecdh.h12
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp4
-rw-r--r--src/pubkey/ecdsa/ecdsa.h6
-rw-r--r--src/pubkey/elgamal/elgamal.cpp10
-rw-r--r--src/pubkey/elgamal/elgamal.h8
-rw-r--r--src/pubkey/gost_3410/gost_3410.cpp20
-rw-r--r--src/pubkey/gost_3410/gost_3410.h8
-rw-r--r--src/pubkey/if_algo/if_algo.cpp10
-rw-r--r--src/pubkey/if_algo/if_algo.h8
-rw-r--r--src/pubkey/keypair/keypair.cpp12
-rw-r--r--src/pubkey/nr/nr.cpp20
-rw-r--r--src/pubkey/nr/nr.h8
-rw-r--r--src/pubkey/pk_algs.cpp8
-rw-r--r--src/pubkey/pk_algs.h4
-rw-r--r--src/pubkey/pk_keys.h6
-rw-r--r--src/pubkey/pk_ops.h10
-rw-r--r--src/pubkey/pkcs8.cpp70
-rw-r--r--src/pubkey/pkcs8.h28
-rw-r--r--src/pubkey/pubkey.cpp60
-rw-r--r--src/pubkey/pubkey.h54
-rw-r--r--src/pubkey/rsa/rsa.cpp12
-rw-r--r--src/pubkey/rsa/rsa.h14
-rw-r--r--src/pubkey/rw/rw.cpp27
-rw-r--r--src/pubkey/rw/rw.h8
-rw-r--r--src/pubkey/workfactor.cpp55
-rw-r--r--src/pubkey/workfactor.h2
-rw-r--r--src/pubkey/x509_key.cpp8
-rw-r--r--src/pubkey/x509_key.h4
-rw-r--r--src/rng/hmac_rng/hmac_rng.cpp13
-rw-r--r--src/rng/hmac_rng/hmac_rng.h2
-rw-r--r--src/rng/randpool/randpool.cpp12
-rw-r--r--src/rng/randpool/randpool.h2
-rw-r--r--src/rng/rng.h4
-rw-r--r--src/rng/x931_rng/x931_rng.cpp2
-rw-r--r--src/rng/x931_rng/x931_rng.h2
-rw-r--r--src/selftest/selftest.cpp3
-rw-r--r--src/ssl/c_kex.cpp165
-rw-r--r--src/ssl/cert_req.cpp151
-rw-r--r--src/ssl/cert_ver.cpp98
-rw-r--r--src/ssl/finished.cpp100
-rw-r--r--src/ssl/hello.cpp331
-rw-r--r--src/ssl/info.txt71
-rw-r--r--src/ssl/rec_read.cpp260
-rw-r--r--src/ssl/rec_wri.cpp270
-rw-r--r--src/ssl/s_kex.cpp180
-rw-r--r--src/ssl/tls_alerts.h54
-rw-r--r--src/ssl/tls_client.cpp586
-rw-r--r--src/ssl/tls_client.h73
-rw-r--r--src/ssl/tls_connection.h36
-rw-r--r--src/ssl/tls_handshake_hash.cpp70
-rw-r--r--src/ssl/tls_handshake_hash.h40
-rw-r--r--src/ssl/tls_magic.h192
-rw-r--r--src/ssl/tls_messages.h297
-rw-r--r--src/ssl/tls_policy.cpp118
-rw-r--r--src/ssl/tls_policy.h63
-rw-r--r--src/ssl/tls_record.h117
-rw-r--r--src/ssl/tls_server.cpp494
-rw-r--r--src/ssl/tls_server.h77
-rw-r--r--src/ssl/tls_session_key.cpp170
-rw-r--r--src/ssl/tls_session_key.h52
-rw-r--r--src/ssl/tls_state.cpp59
-rw-r--r--src/ssl/tls_state.h53
-rw-r--r--src/ssl/tls_suites.cpp281
-rw-r--r--src/ssl/tls_suites.h42
-rw-r--r--src/stream/arc4/arc4.cpp18
-rw-r--r--src/stream/arc4/arc4.h4
-rw-r--r--src/stream/ctr/ctr.cpp6
-rw-r--r--src/stream/ctr/ctr.h2
-rw-r--r--src/stream/ofb/ofb.cpp4
-rw-r--r--src/stream/ofb/ofb.h2
-rw-r--r--src/stream/salsa20/salsa20.cpp11
-rw-r--r--src/stream/salsa20/salsa20.h6
-rw-r--r--src/stream/turing/turing.cpp26
-rw-r--r--src/stream/turing/turing.h10
-rw-r--r--src/stream/wid_wake/wid_wake.cpp13
-rw-r--r--src/stream/wid_wake/wid_wake.h12
-rw-r--r--src/tls/c_hello.cpp394
-rw-r--r--src/tls/c_kex.cpp393
-rw-r--r--src/tls/cert_req.cpp241
-rw-r--r--src/tls/cert_ver.cpp117
-rw-r--r--src/tls/finished.cpp104
-rw-r--r--src/tls/hello_verify.cpp61
-rw-r--r--src/tls/info.txt95
-rw-r--r--src/tls/next_protocol.cpp55
-rw-r--r--src/tls/rec_read.cpp353
-rw-r--r--src/tls/rec_wri.cpp317
-rw-r--r--src/tls/s_hello.cpp186
-rw-r--r--src/tls/s_kex.cpp292
-rw-r--r--src/tls/session_ticket.cpp57
-rw-r--r--src/tls/sessions_sqlite/info.txt11
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp350
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h71
-rw-r--r--src/tls/tls_alert.cpp122
-rw-r--r--src/tls/tls_alert.h100
-rw-r--r--src/tls/tls_channel.cpp326
-rw-r--r--src/tls/tls_channel.h155
-rw-r--r--src/tls/tls_ciphersuite.cpp104
-rw-r--r--src/tls/tls_ciphersuite.h73
-rw-r--r--src/tls/tls_client.cpp486
-rw-r--r--src/tls/tls_client.h74
-rw-r--r--src/tls/tls_exceptn.h (renamed from src/ssl/tls_exceptn.h)14
-rw-r--r--src/tls/tls_extensions.cpp524
-rw-r--r--src/tls/tls_extensions.h381
-rw-r--r--src/tls/tls_handshake_hash.cpp103
-rw-r--r--src/tls/tls_handshake_hash.h58
-rw-r--r--src/tls/tls_handshake_reader.cpp66
-rw-r--r--src/tls/tls_handshake_reader.h58
-rw-r--r--src/tls/tls_handshake_state.cpp330
-rw-r--r--src/tls/tls_handshake_state.h112
-rw-r--r--src/tls/tls_heartbeats.cpp78
-rw-r--r--src/tls/tls_heartbeats.h40
-rw-r--r--src/tls/tls_magic.h69
-rw-r--r--src/tls/tls_messages.h501
-rw-r--r--src/tls/tls_policy.cpp265
-rw-r--r--src/tls/tls_policy.h127
-rw-r--r--src/tls/tls_reader.h (renamed from src/ssl/tls_reader.h)74
-rw-r--r--src/tls/tls_record.h136
-rw-r--r--src/tls/tls_server.cpp620
-rw-r--r--src/tls/tls_server.h74
-rw-r--r--src/tls/tls_session.cpp251
-rw-r--r--src/tls/tls_session.h217
-rw-r--r--src/tls/tls_session_key.cpp89
-rw-r--r--src/tls/tls_session_key.h52
-rw-r--r--src/tls/tls_session_manager.cpp106
-rw-r--r--src/tls/tls_session_manager.h127
-rw-r--r--src/tls/tls_suite_info.cpp317
-rw-r--r--src/tls/tls_version.cpp33
-rw-r--r--src/tls/tls_version.h87
-rw-r--r--src/utils/assert.cpp2
-rw-r--r--src/utils/assert.h10
-rw-r--r--src/utils/calendar.cpp52
-rw-r--r--src/utils/calendar.h (renamed from src/utils/time.h)22
-rw-r--r--src/utils/charset.cpp2
-rw-r--r--src/utils/cpuid.h2
-rw-r--r--src/utils/datastor/datastor.cpp56
-rw-r--r--src/utils/datastor/datastor.h22
-rw-r--r--src/utils/dyn_load/dyn_load.cpp4
-rw-r--r--src/utils/dyn_load/dyn_load.h3
-rw-r--r--src/utils/exceptn.h4
-rw-r--r--src/utils/info.txt8
-rw-r--r--src/utils/mlock.cpp54
-rw-r--r--src/utils/mlock.h37
-rw-r--r--src/utils/parsing.cpp93
-rw-r--r--src/utils/parsing.h30
-rw-r--r--src/utils/rounding.h18
-rw-r--r--src/utils/stl_util.h63
-rw-r--r--src/utils/time.cpp125
-rw-r--r--src/utils/types.h10
-rw-r--r--src/utils/ui.cpp36
-rw-r--r--src/utils/ui.h37
-rw-r--r--src/utils/xor_buf.h26
-rw-r--r--src/wrap/python/core.cpp2
-rw-r--r--src/wrap/python/filter.cpp14
-rw-r--r--src/wrap/python/python_botan.h5
-rw-r--r--src/wrap/python/rsa.cpp4
-rw-r--r--src/wrap/python/x509.cpp2
594 files changed, 15802 insertions, 10114 deletions
diff --git a/botan_version.py b/botan_version.py
index a44619e71..eada52c86 100644
--- a/botan_version.py
+++ b/botan_version.py
@@ -1,6 +1,6 @@
release_major = 1
-release_minor = 10
+release_minor = 99
release_patch = 2
release_vc_rev = None
diff --git a/checks/bench.cpp b/checks/bench.cpp
index e9eb92199..5faba00db 100644
--- a/checks/bench.cpp
+++ b/checks/bench.cpp
@@ -14,9 +14,12 @@
#include <botan/engine.h>
#include <botan/parsing.h>
#include <botan/symkey.h>
-#include <botan/time.h>
#include <botan/hex.h>
+#include <chrono>
+
+typedef std::chrono::high_resolution_clock benchmark_clock;
+
#include "common.h"
#include "bench.h"
@@ -150,18 +153,6 @@ void report_results(const std::string& algo,
std::cout << algo;
-#if defined(__SUNPRO_CC)
- #define REVERSE_ITERATOR_BUG 1
-#elif defined(__GNUC__) && __GNUC__ <= 3
- #define REVERSE_ITERATOR_BUG 1
-#elif defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
- #define REVERSE_ITERATOR_BUG 1
-#endif
-
-#ifndef REVERSE_ITERATOR_BUG
- #define REVERSE_ITERATOR_BUG 0
-#endif
-
#if (defined(__GNUC__) && __GNUC__ <= 3) || defined(__SUNPRO_CC)
// Work around GCC 3.x bug, reverse iterators don't work
for(std::map<double, std::string>::const_iterator i = results.begin(); i != results.end(); ++i)
@@ -184,10 +175,11 @@ bool bench_algo(const std::string& algo,
{
Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
- u32bit milliseconds = static_cast<u32bit>(seconds * 1000);
+ std::chrono::milliseconds ms(
+ static_cast<std::chrono::milliseconds::rep>(seconds * 1000));
std::map<std::string, double> speeds =
- algorithm_benchmark(algo, af, rng, milliseconds, buf_size);
+ algorithm_benchmark(algo, af, rng, ms, buf_size);
if(speeds.empty()) // maybe a cipher mode, then?
{
@@ -236,17 +228,23 @@ bool bench_algo(const std::string& algo,
Botan::Pipe pipe(filt, new Botan::BitBucket);
pipe.start_msg();
- const u64bit start = Botan::get_nanoseconds_clock();
- u64bit nanoseconds_used = 0;
+ std::chrono::nanoseconds max_time(nanoseconds_max);
+ std::chrono::nanoseconds time_used(0);
+
+ auto start = benchmark_clock::now();
+
u64bit reps = 0;
- while(nanoseconds_used < nanoseconds_max)
+ while(time_used < max_time)
{
pipe.write(&buf[0], buf.size());
++reps;
- nanoseconds_used = Botan::get_nanoseconds_clock() - start;
+ time_used = benchmark_clock::now() - start;
}
+ u64bit nanoseconds_used =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count();
+
double mbytes_per_second =
(953.67 * (buf.size() * reps)) / nanoseconds_used;
diff --git a/checks/common.h b/checks/common.h
index 33499a99d..05a6fb974 100644
--- a/checks/common.h
+++ b/checks/common.h
@@ -55,13 +55,13 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator
void clear() throw() {}
- Fixed_Output_RNG(const Botan::SecureVector<byte>& in)
+ Fixed_Output_RNG(const Botan::secure_vector<byte>& in)
{
buf.insert(buf.end(), in.begin(), in.end());
}
Fixed_Output_RNG(const std::string& in_str)
{
- Botan::SecureVector<byte> in = Botan::hex_decode(in_str);
+ Botan::secure_vector<byte> in = Botan::hex_decode(in_str);
buf.insert(buf.end(), in.begin(), in.end());
}
diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp
index 334fb8581..9dc56610c 100644
--- a/checks/cvc_tests.cpp
+++ b/checks/cvc_tests.cpp
@@ -27,7 +27,6 @@
#include <botan/cvc_self.h>
#include <botan/cvc_cert.h>
#include <botan/cvc_ado.h>
-#include <botan/time.h>
#define TEST_DATA_DIR "checks/ecc_testdata"
@@ -41,7 +40,7 @@ namespace {
// helper functions
void helper_write_file(EAC_Signed_Object const& to_write, std::string const& file_path)
{
- SecureVector<byte> sv = to_write.BER_encode();
+ std::vector<byte> sv = to_write.BER_encode();
std::ofstream cert_file(file_path.c_str(), std::ios::binary);
cert_file.write((char*)&sv[0], sv.size());
cert_file.close();
@@ -51,8 +50,8 @@ bool helper_files_equal(std::string const& file_path1, std::string const& file_p
{
std::ifstream cert_1_in(file_path1.c_str());
std::ifstream cert_2_in(file_path2.c_str());
- SecureVector<byte> sv1;
- SecureVector<byte> sv2;
+ std::vector<byte> sv1;
+ std::vector<byte> sv2;
if (!cert_1_in || !cert_2_in)
{
return false;
@@ -95,7 +94,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng);
- SecureVector<byte> der(cert.BER_encode());
+ std::vector<byte> der(cert.BER_encode());
std::ofstream cert_file;
cert_file.open(TEST_DATA_DIR "/my_cv_cert.ber", std::ios::binary);
//cert_file << der; // this is bad !!!
@@ -105,15 +104,15 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
EAC1_1_CVC cert_in(TEST_DATA_DIR "/my_cv_cert.ber");
CHECK(cert == cert_in);
// encoding it again while it has no dp
- SecureVector<byte> der2(cert_in.BER_encode());
+ std::vector<byte> der2(cert_in.BER_encode());
std::ofstream cert_file2(TEST_DATA_DIR "/my_cv_cert2.ber", std::ios::binary);
cert_file2.write((char*)&der2[0], der2.size());
cert_file2.close();
// read both and compare them
std::ifstream cert_1_in(TEST_DATA_DIR "/my_cv_cert.ber");
std::ifstream cert_2_in(TEST_DATA_DIR "/my_cv_cert2.ber");
- SecureVector<byte> sv1;
- SecureVector<byte> sv2;
+ std::vector<byte> sv1;
+ std::vector<byte> sv2;
if (!cert_1_in || !cert_2_in)
{
CHECK_MESSAGE(false, "could not read certificate files");
@@ -162,12 +161,12 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
}
CHECK(ill_date_exc2);
//cout << "readable = '" << cert_in.get_ced().readable_string() << "'\n";
- std::auto_ptr<Public_Key> p_pk(cert_in.subject_public_key());
- //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk));
+ std::unique_ptr<Public_Key> p_pk(cert_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
+
// let´s see if encoding is truely implicitca, because this is what the key should have
// been set to when decoding (see above)(because it has no domain params):
- //cout << "encoding = " << p_ecdsa_pk->get_parameter_encoding() << std::endl;
+
CHECK(p_ecdsa_pk->domain_format() == EC_DOMPAR_ENC_IMPLICITCA);
bool exc = false;
try
@@ -181,7 +180,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
CHECK(exc);
// set them and try again
//cert_in.set_domain_parameters(dom_pars);
- std::auto_ptr<Public_Key> p_pk2(cert_in.subject_public_key());
+ std::unique_ptr<Public_Key> p_pk2(cert_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
//p_ecdsa_pk2->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk2->domain().get_order() == dom_pars.get_order());
@@ -204,7 +203,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng)
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);
- SecureVector<byte> der(req.BER_encode());
+ std::vector<byte> der(req.BER_encode());
std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
req_file.write((char*)&der[0], der.size());
req_file.close();
@@ -212,7 +211,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng)
// read and check signature...
EAC1_1_Req req_in(TEST_DATA_DIR "/my_cv_req.ber");
//req_in.set_domain_parameters(dom_pars);
- std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key());
+ std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
//p_ecdsa_pk->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order());
@@ -227,7 +226,7 @@ void test_cvc_req_ext(RandomNumberGenerator&)
EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
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::auto_ptr<Public_Key> p_pk(req_in.subject_public_key());
+ std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
//p_ecdsa_pk->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order());
@@ -261,7 +260,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng)
req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
//EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
- SecureVector<byte> der(req.BER_encode());
+ std::vector<byte> der(req.BER_encode());
std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
req_file.write((char*)&der[0], der.size());
req_file.close();
@@ -277,7 +276,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng)
CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
std::ofstream ado_file(TEST_DATA_DIR "/ado", std::ios::binary);
- SecureVector<byte> ado_der(ado.BER_encode());
+ std::vector<byte> ado_der(ado.BER_encode());
ado_file.write((char*)&ado_der[0], ado_der.size());
ado_file.close();
// read it again and check the signature
@@ -333,7 +332,7 @@ void test_cvc_ado_comparison(RandomNumberGenerator& rng)
CHECK_MESSAGE(ado != ado2, "ado's found to be equal where they are not");
// std::ofstream ado_file(TEST_DATA_DIR "/ado");
- // SecureVector<byte> ado_der(ado.BER_encode());
+ // std::vector<byte> ado_der(ado.BER_encode());
// ado_file.write((char*)&ado_der[0], ado_der.size());
// ado_file.close();
// read it again and check the signature
@@ -349,8 +348,7 @@ void test_eac_time(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
- const u64bit current_time = system_time();
- EAC_Time time(current_time);
+ EAC_Time time(std::chrono::system_clock::now());
// std::cout << "time as std::string = " << time.as_string() << std::endl;
EAC_Time sooner("", ASN1_Tag(99));
//X509_Time sooner("", ASN1_Tag(99));
@@ -389,11 +387,9 @@ void test_ver_cvca(RandomNumberGenerator&)
EAC1_1_CVC req_in(TEST_DATA_DIR "/cvca01.cv.crt");
- //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk));
- //ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
bool exc = false;
- std::auto_ptr<Public_Key> p_pk2(req_in.subject_public_key());
+ std::unique_ptr<Public_Key> p_pk2(req_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
bool ver_ec = req_in.check_signature(*p_pk2);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvca certificate");
@@ -494,7 +490,7 @@ void test_cvc_chain(RandomNumberGenerator& rng)
ASN1_Car car("DECVCA00001");
EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, rng);
std::ofstream cvca_file(TEST_DATA_DIR "/cvc_chain_cvca.cer", std::ios::binary);
- SecureVector<byte> cvca_sv = cvca_cert.BER_encode();
+ std::vector<byte> cvca_sv = cvca_cert.BER_encode();
cvca_file.write((char*)&cvca_sv[0], cvca_sv.size());
cvca_file.close();
@@ -502,7 +498,7 @@ void test_cvc_chain(RandomNumberGenerator& rng)
ASN1_Car car2("DECVCA00002");
EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, rng);
EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, rng);
- SecureVector<byte> link12_sv = link12.BER_encode();
+ std::vector<byte> link12_sv = link12.BER_encode();
std::ofstream link12_file(TEST_DATA_DIR "/cvc_chain_link12.cer", std::ios::binary);
link12_file.write((char*)&link12_sv[0], link12_sv.size());
link12_file.close();
@@ -511,14 +507,14 @@ void test_cvc_chain(RandomNumberGenerator& rng)
CHECK(link12.check_signature(cvca_privk));
EAC1_1_CVC link12_reloaded(TEST_DATA_DIR "/cvc_chain_link12.cer");
EAC1_1_CVC cvca1_reloaded(TEST_DATA_DIR "/cvc_chain_cvca.cer");
- std::auto_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key());
+ std::unique_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key());
CHECK(link12_reloaded.check_signature(*cvca1_rel_pk));
// create first round dvca-req
ECDSA_PrivateKey dvca_priv_key(rng, dom_pars);
EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, rng);
std::ofstream dvca_file(TEST_DATA_DIR "/cvc_chain_dvca_req.cer", std::ios::binary);
- SecureVector<byte> dvca_sv = dvca_req.BER_encode();
+ std::vector<byte> dvca_sv = dvca_req.BER_encode();
dvca_file.write((char*)&dvca_sv[0], dvca_sv.size());
dvca_file.close();
@@ -532,7 +528,7 @@ void test_cvc_chain(RandomNumberGenerator& rng)
ECDSA_PrivateKey dvca_priv_key2(rng, dom_pars);
EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, rng);
std::ofstream dvca_file2(TEST_DATA_DIR "/cvc_chain_dvca_req2.cer", std::ios::binary);
- SecureVector<byte> dvca_sv2 = dvca_req2.BER_encode();
+ std::vector<byte> dvca_sv2 = dvca_req2.BER_encode();
dvca_file2.write((char*)&dvca_sv2[0], dvca_sv2.size());
dvca_file2.close();
EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2,
@@ -541,7 +537,7 @@ void test_cvc_chain(RandomNumberGenerator& rng)
// verify the ado and sign the request too
- std::auto_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key());
+ std::unique_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key());
ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get());
//cert_pk->set_domain_parameters(dom_pars);
diff --git a/checks/dolook.cpp b/checks/dolook.cpp
index a8e08a96b..364a3f8c3 100644
--- a/checks/dolook.cpp
+++ b/checks/dolook.cpp
@@ -83,14 +83,14 @@ class PBKDF_Filter : public Filter
pbkdf = algo;
outlen = o;
iterations = i;
- salt = s.bits_of();
+ salt = unlock(s.bits_of());
}
~PBKDF_Filter() { delete pbkdf; }
private:
std::string passphrase;
PBKDF* pbkdf;
- SecureVector<byte> salt;
+ std::vector<byte> salt;
u32bit outlen, iterations;
};
@@ -126,12 +126,12 @@ class KDF_Filter : public Filter
{
kdf = algo;
outlen = o;
- salt = s.bits_of();
+ salt = unlock(s.bits_of());
}
~KDF_Filter() { delete kdf; }
private:
- SecureVector<byte> secret;
- SecureVector<byte> salt;
+ std::vector<byte> secret;
+ std::vector<byte> salt;
KDF* kdf;
u32bit outlen;
};
@@ -139,7 +139,7 @@ class KDF_Filter : public Filter
Filter* lookup_pbkdf(const std::string& algname,
const std::vector<std::string>& params)
{
- PBKDF* pbkdf = 0;
+ PBKDF* pbkdf = nullptr;
try {
pbkdf = get_pbkdf(algname);
@@ -149,7 +149,7 @@ Filter* lookup_pbkdf(const std::string& algname,
if(pbkdf)
return new PBKDF_Filter(pbkdf, params[0], to_u32bit(params[1]),
to_u32bit(params[2]));
- return 0;
+ return nullptr;
}
void RNG_Filter::write(const byte[], size_t length)
@@ -163,7 +163,7 @@ void RNG_Filter::write(const byte[], size_t length)
Filter* lookup_rng(const std::string& algname,
const std::string& key)
{
- RandomNumberGenerator* prng = 0;
+ RandomNumberGenerator* prng = nullptr;
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
if(algname == "AutoSeeded")
@@ -233,21 +233,21 @@ Filter* lookup_rng(const std::string& algname,
return new RNG_Filter(prng);
}
- return 0;
+ return nullptr;
}
Filter* lookup_kdf(const std::string& algname, const std::string& salt,
const std::string& params)
{
- KDF* kdf = 0;
+ KDF* kdf = nullptr;
try {
kdf = get_kdf(algname);
}
- catch(...) { return 0; }
+ catch(...) { return nullptr; }
if(kdf)
return new KDF_Filter(kdf, salt, to_u32bit(params));
- return 0;
+ return nullptr;
}
Filter* lookup_encoder(const std::string& algname)
@@ -278,7 +278,7 @@ Filter* lookup_encoder(const std::string& algname)
return new Zlib_Decompression;
#endif
- return 0;
+ return nullptr;
}
}
@@ -288,7 +288,7 @@ Filter* lookup(const std::string& algname,
{
std::string key = params[0];
std::string iv = params[1];
- Filter* filter = 0;
+ Filter* filter = nullptr;
// The order of the lookup has to change based on how the names are
// formatted and parsed.
@@ -304,6 +304,6 @@ Filter* lookup(const std::string& algname,
filter = lookup_pbkdf(algname, params);
if(filter) return filter;
- return 0;
+ return nullptr;
}
diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp
index 8ed975603..39c32de37 100644
--- a/checks/ec_tests.cpp
+++ b/checks/ec_tests.cpp
@@ -76,10 +76,10 @@ void test_point_turn_on_sp_red_mul()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode(p_secp);
- SecureVector<byte> sv_a_secp = hex_decode(a_secp);
- SecureVector<byte> sv_b_secp = hex_decode(b_secp);
- SecureVector<byte> sv_G_secp_comp = hex_decode(G_secp_comp);
+ secure_vector<byte> sv_p_secp = hex_decode(p_secp);
+ secure_vector<byte> sv_a_secp = hex_decode(a_secp);
+ secure_vector<byte> sv_b_secp = hex_decode(b_secp);
+ secure_vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp);
BigInt bi_p_secp = BigInt::decode(&sv_p_secp[0], sv_p_secp.size());
BigInt bi_a_secp = BigInt::decode(&sv_a_secp[0], sv_a_secp.size());
BigInt bi_b_secp = BigInt::decode(&sv_b_secp[0], sv_b_secp.size());
@@ -139,10 +139,10 @@ void test_coordinates()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
@@ -196,7 +196,7 @@ void test_point_mult ()
const CurveGFp& curve = secp160r1.get_curve();
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_G_secp_comp = hex_decode(G_secp_comp);
+ secure_vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp);
PointGFp p_G = OS2ECP(sv_G_secp_comp, curve);
BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982");
@@ -215,10 +215,10 @@ void test_point_negative()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
@@ -242,7 +242,7 @@ void test_zeropoint()
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
@@ -273,7 +273,7 @@ void test_zeropoint_enc_dec()
CHECK_MESSAGE( p.is_zero(), "by constructor created zeropoint is no zeropoint!");
- SecureVector<byte> sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED);
+ secure_vector<byte> sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED);
PointGFp p_encdec = OS2ECP(sv_p, curve);
CHECK_MESSAGE( p == p_encdec, "encoded-decoded (uncompressed) point is not equal the original!");
@@ -291,7 +291,7 @@ void test_calc_with_zeropoint()
std::cout << "." << std::flush;
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
@@ -327,10 +327,10 @@ void test_add_point()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
@@ -363,10 +363,10 @@ void test_sub_point()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
@@ -398,10 +398,10 @@ void test_mult_point()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
@@ -427,10 +427,10 @@ void test_basic_operations()
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
@@ -490,10 +490,10 @@ void test_enc_dec_compressed_160()
std::string G_secp_comp = "024A96B5688EF573284664698968C38BB913CBFC82";
std::string G_order_secp_comp = "0100000000000000000001F4C8F927AED3CA752257";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
@@ -502,7 +502,7 @@ void test_enc_dec_compressed_160()
CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp);
PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
- SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
+ secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
CHECK( sv_result == sv_G_secp_comp);
}
@@ -519,10 +519,10 @@ void test_enc_dec_compressed_256()
std::string G_secp_comp = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296";
std::string G_order_secp_comp = "ffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
@@ -531,7 +531,7 @@ void test_enc_dec_compressed_256()
CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp);
PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
- SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
+ secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
CHECK( sv_result == sv_G_secp_comp);
}
@@ -550,10 +550,10 @@ void test_enc_dec_uncompressed_112()
std::string G_secp_uncomp = "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97";
std::string G_order_secp_uncomp = "36DF0AAFD8B8D7597CA10520D04B";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
@@ -562,7 +562,7 @@ void test_enc_dec_uncompressed_112()
CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp);
PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 );
- SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
+ secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
CHECK( sv_result == sv_G_secp_uncomp);
}
@@ -579,10 +579,10 @@ void test_enc_dec_uncompressed_521()
std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
@@ -592,7 +592,7 @@ void test_enc_dec_uncompressed_521()
PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 );
- SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
+ secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
std::string result = hex_encode(&sv_result[0], sv_result.size());
std::string exp_result = hex_encode(&sv_G_secp_uncomp[0], sv_G_secp_uncomp.size());
@@ -611,21 +611,21 @@ void test_enc_dec_uncompressed_521_prime_too_large()
std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409";
- SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
+ secure_vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp );
BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() );
CurveGFp secp521r1 (bi_p_secp, bi_a_secp, bi_b_secp);
- std::auto_ptr<PointGFp> p_G;
+ std::unique_ptr<PointGFp> p_G;
bool exc = false;
try
{
- p_G = std::auto_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1)));
+ p_G = std::unique_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1)));
if(!p_G->on_the_curve())
throw Internal_Error("Point not on the curve");
}
@@ -648,7 +648,7 @@ void test_gfp_store_restore()
PointGFp p = dom_pars.get_base_point();
//store point (to std::string)
- SecureVector<byte> sv_mes = EC2OSP(p, PointGFp::COMPRESSED);
+ secure_vector<byte> sv_mes = EC2OSP(p, PointGFp::COMPRESSED);
PointGFp new_p = OS2ECP(sv_mes, dom_pars.get_curve());
CHECK_MESSAGE( p == new_p, "original and restored point are different!");
@@ -662,7 +662,7 @@ void test_cdc_curve_33()
std::string G_secp_uncomp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
- SecureVector<byte> sv_G_uncomp = hex_decode ( G_secp_uncomp );
+ secure_vector<byte> sv_G_uncomp = hex_decode ( G_secp_uncomp );
BigInt bi_p_secp = BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
BigInt bi_a_secp("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe");
@@ -689,7 +689,7 @@ void test_more_zeropoint()
// by Falko
std::string G = "024a96b5688ef573284664698968c38bb913cbfc82";
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G );
BigInt bi_p("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp
index c641796d6..841bce55b 100644
--- a/checks/ecdh.cpp
+++ b/checks/ecdh.cpp
@@ -96,8 +96,8 @@ void test_ecdh_der_derivation(RandomNumberGenerator& rng)
ECDH_PrivateKey private_a(rng, dom_pars);
ECDH_PrivateKey private_b(rng, dom_pars);
- MemoryVector<byte> key_a = private_a.public_value();
- MemoryVector<byte> key_b = private_b.public_value();
+ std::vector<byte> key_a = private_a.public_value();
+ std::vector<byte> key_b = private_b.public_value();
PK_Key_Agreement ka(private_a, "KDF2(SHA-1)");
PK_Key_Agreement kb(private_b, "KDF2(SHA-1)");
diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp
index 5cf353e58..554f72dd7 100644
--- a/checks/ecdsa.cpp
+++ b/checks/ecdsa.cpp
@@ -32,7 +32,7 @@ using namespace Botan;
namespace {
-std::string to_hex(const SecureVector<byte>& bin)
+std::string to_hex(const std::vector<byte>& bin)
{
return hex_encode(&bin[0], bin.size());
}
@@ -54,7 +54,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng)
ECDSA_PrivateKey priv_key(rng, dom_pars);
- SecureVector<byte> message(20);
+ std::vector<byte> message(20);
for(size_t i = 0; i != message.size(); ++i)
message[i] = i;
@@ -64,14 +64,14 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng)
PK_Signer pk_signer_224(priv_key, "EMSA1_BSI(SHA-224)");
// Verify we can sign and verify with SHA-160
- SecureVector<byte> signature_160 = pk_signer_160.sign_message(message, rng);
+ std::vector<byte> signature_160 = pk_signer_160.sign_message(message, rng);
CHECK(pk_verifier_160.verify_message(message, signature_160));
bool signature_failed = false;
try
{
- SecureVector<byte> signature_224 = pk_signer_224.sign_message(message, rng);
+ std::vector<byte> signature_224 = pk_signer_224.sign_message(message, rng);
}
catch(Encoding_Error)
{
@@ -84,7 +84,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng)
// sign it with the normal EMSA1
PK_Signer pk_signer(priv_key, "EMSA1(SHA-224)");
- SecureVector<byte> signature = pk_signer.sign_message(message, rng);
+ std::vector<byte> signature = pk_signer.sign_message(message, rng);
PK_Verifier pk_verifier(priv_key, "EMSA1_BSI(SHA-224)");
@@ -104,7 +104,7 @@ void test_decode_ecdsa_X509()
CHECK_MESSAGE(to_hex(cert.authority_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading authority key id from x509 ecdsa certificate");
CHECK_MESSAGE(to_hex(cert.subject_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading Subject key id from x509 ecdsa certificate");
- std::auto_ptr<X509_PublicKey> pubkey(cert.subject_public_key());
+ std::unique_ptr<X509_PublicKey> pubkey(cert.subject_public_key());
bool ver_ec = cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned x509-ecdsa certificate");
}
@@ -116,7 +116,7 @@ void test_decode_ver_link_SHA256()
X509_Certificate root_cert(TEST_DATA_DIR "/root2_SHA256.cer");
X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA256.cer");
- std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
+ std::unique_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
bool ver_ec = link_cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA256 link x509-ecdsa certificate");
@@ -128,7 +128,7 @@ void test_decode_ver_link_SHA1()
X509_Certificate root_cert(TEST_DATA_DIR "/root_SHA1.163.crt");
X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA1.166.crt");
- std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
+ std::unique_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
bool ver_ec = link_cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA1 link x509-ecdsa certificate");
}
@@ -142,8 +142,8 @@ void test_sign_then_ver(RandomNumberGenerator& rng)
PK_Signer signer(ecdsa, "EMSA1(SHA-1)");
- SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12");
- SecureVector<byte> sig = signer.sign_message(msg, rng);
+ secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12");
+ std::vector<byte> sig = signer.sign_message(msg, rng);
PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)");
@@ -174,7 +174,7 @@ bool test_ec_sign(RandomNumberGenerator& rng)
for(size_t i = 0; i != 256; ++i)
signer.update(static_cast<byte>(i));
- SecureVector<byte> sig = signer.signature(rng);
+ std::vector<byte> sig = signer.signature(rng);
for(u32bit i = 0; i != 256; ++i)
verifier.update(static_cast<byte>(i));
@@ -251,11 +251,11 @@ void test_create_and_verify(RandomNumberGenerator& rng)
std::ofstream priv_key(TEST_DATA_DIR "/dompar_private.pkcs8.pem");
priv_key << PKCS8::PEM_encode(key);
- std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
- std::auto_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng));
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_rsa_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_1.get());
CHECK_MESSAGE(!loaded_rsa_key, "the loaded key is ECDSA_PrivateKey -> shouldn't be, is a RSA-Key");
@@ -267,11 +267,11 @@ void test_create_and_verify(RandomNumberGenerator& rng)
std::string G_secp_comp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
std::string order_g = "0e1a16196e6000000000bc7f1618d867b15bb86474418f";
- // ::SecureVector<byte> sv_p_secp = hex_decode ( p_secp );
- SecureVector<byte> sv_a_secp = hex_decode ( a_secp );
- SecureVector<byte> sv_b_secp = hex_decode ( b_secp );
- SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
- SecureVector<byte> sv_order_g = hex_decode ( order_g );
+ // ::std::vector<byte> sv_p_secp = hex_decode ( p_secp );
+ secure_vector<byte> sv_a_secp = hex_decode ( a_secp );
+ secure_vector<byte> sv_b_secp = hex_decode ( b_secp );
+ secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp );
+ secure_vector<byte> sv_order_g = hex_decode ( order_g );
// BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() );
BigInt bi_p_secp("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
@@ -289,7 +289,7 @@ void test_create_and_verify(RandomNumberGenerator& rng)
std::string key_odd_oid_str = PKCS8::PEM_encode(key_odd_oid);
DataSource_Memory key_data_src(key_odd_oid_str);
- std::auto_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng));
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng));
if(!dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get()))
{
@@ -343,8 +343,8 @@ void test_curve_registry(RandomNumberGenerator& rng)
PK_Signer signer(ecdsa, "EMSA1(SHA-1)");
PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)");
- SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12");
- SecureVector<byte> sig = signer.sign_message(msg, rng);
+ secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12");
+ std::vector<byte> sig = signer.sign_message(msg, rng);
if(!verifier.verify_message(msg, sig))
std::cout << "Failed testing ECDSA sig for curve " << oids[i] << "\n";
@@ -361,17 +361,17 @@ void test_read_pkcs8(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12");
+ secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12");
try
{
- std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
ECDSA_PrivateKey* ecdsa = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
CHECK_MESSAGE(ecdsa, "the loaded key could not be converted into an ECDSA_PrivateKey");
PK_Signer signer(*ecdsa, "EMSA1(SHA-1)");
- SecureVector<byte> sig = signer.sign_message(msg, rng);
+ std::vector<byte> sig = signer.sign_message(msg, rng);
PK_Verifier verifier(*ecdsa, "EMSA1(SHA-1)");
@@ -385,7 +385,7 @@ void test_read_pkcs8(RandomNumberGenerator& rng)
try
{
- std::auto_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng));
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng));
// anew in each test with unregistered domain-parameters
ECDSA_PrivateKey* ecdsa_nodp = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_nodp.get());
CHECK_MESSAGE(ecdsa_nodp, "the loaded key could not be converted into an ECDSA_PrivateKey");
@@ -393,14 +393,14 @@ void test_read_pkcs8(RandomNumberGenerator& rng)
PK_Signer signer(*ecdsa_nodp, "EMSA1(SHA-1)");
PK_Verifier verifier(*ecdsa_nodp, "EMSA1(SHA-1)");
- SecureVector<byte> signature_nodp = signer.sign_message(msg, rng);
+ std::vector<byte> signature_nodp = signer.sign_message(msg, rng);
CHECK_MESSAGE(verifier.verify_message(msg, signature_nodp),
"generated signature could not be verified positively (no_dom)");
try
{
- std::auto_ptr<PKCS8_PrivateKey> loaded_key_withdp(
+ std::unique_ptr<PKCS8_PrivateKey> loaded_key_withdp(
PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng));
std::cout << "Unexpected success: loaded key with unknown OID\n";
diff --git a/checks/pk.cpp b/checks/pk.cpp
index 6291b1566..5ef5df94b 100644
--- a/checks/pk.cpp
+++ b/checks/pk.cpp
@@ -14,6 +14,12 @@
#include <botan/botan.h>
#include <botan/oids.h>
+#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
+ #include <botan/x509_key.h>
+ #include <botan/pkcs8.h>
+ #include <botan/pubkey.h>
+#endif
+
#if defined(BOTAN_HAS_RSA)
#include <botan/rsa.h>
#endif
@@ -79,8 +85,8 @@ BigInt to_bigint(std::string input)
input.length(), BigInt::Hexadecimal);
}
-void dump_data(const SecureVector<byte>& out,
- const SecureVector<byte>& expected)
+void dump_data(const std::vector<byte>& out,
+ const std::vector<byte>& expected)
{
Pipe pipe(new Hex_Encoder);
@@ -102,7 +108,7 @@ void validate_save_and_load(const Private_Key* priv_key,
DataSource_Memory input_pub(pub_pem);
std::auto_ptr<Public_Key> restored_pub(X509::load_key(input_pub));
- if(restored_pub.get() == 0)
+ if(!restored_pub.get())
std::cout << "Could not recover " << name << " public key\n";
else if(restored_pub->check_key(rng, true) == false)
std::cout << "Restored pubkey failed self tests " << name << "\n";
@@ -122,7 +128,7 @@ void validate_save_and_load(const Private_Key* priv_key,
std::auto_ptr<Private_Key> restored_priv(
PKCS8::load_key(input_priv, rng));
- if(restored_priv.get() == 0)
+ if(!restored_priv.get())
std::cout << "Could not recover " << name << " privlic key\n";
else if(restored_priv->check_key(rng, true) == false)
std::cout << "Restored privkey failed self tests " << name << "\n";
@@ -136,11 +142,11 @@ void validate_save_and_load(const Private_Key* priv_key,
}
void validate_decryption(PK_Decryptor& d, const std::string& algo,
- const SecureVector<byte> ctext,
- const SecureVector<byte> ptext,
+ const std::vector<byte> ctext,
+ const std::vector<byte> ptext,
bool& failure)
{
- SecureVector<byte> decrypted = d.decrypt(ctext);
+ std::vector<byte> decrypted = unlock(d.decrypt(ctext));
if(decrypted != ptext)
{
std::cout << "FAILED (decrypt): " << algo << std::endl;
@@ -154,11 +160,11 @@ void validate_encryption(PK_Encryptor& e, PK_Decryptor& d,
const std::string& random, const std::string& exp,
bool& failure)
{
- SecureVector<byte> message = hex_decode(input);
- SecureVector<byte> expected = hex_decode(exp);
+ std::vector<byte> message = unlock(hex_decode(input));
+ std::vector<byte> expected = unlock(hex_decode(exp));
Fixed_Output_RNG rng(hex_decode(random));
- SecureVector<byte> out = e.encrypt(message, rng);
+ std::vector<byte> out = e.encrypt(message, rng);
if(out != expected)
{
std::cout << "FAILED (encrypt): " << algo << std::endl;
@@ -174,11 +180,11 @@ void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo,
RandomNumberGenerator& rng,
const std::string& exp, bool& failure)
{
- SecureVector<byte> message = hex_decode(input);
+ std::vector<byte> message = unlock(hex_decode(input));
- SecureVector<byte> expected = hex_decode(exp);
+ std::vector<byte> expected = unlock(hex_decode(exp));
- SecureVector<byte> sig = s.sign_message(message, rng);
+ std::vector<byte> sig = s.sign_message(message, rng);
if(sig != expected)
{
@@ -214,18 +220,18 @@ void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo,
}
void validate_kas(PK_Key_Agreement& kas, const std::string& algo,
- const SecureVector<byte>& pubkey, const std::string& output,
+ const std::vector<byte>& pubkey, const std::string& output,
u32bit keylen, bool& failure)
{
- SecureVector<byte> expected = hex_decode(output);
+ secure_vector<byte> expected = hex_decode(output);
- SecureVector<byte> got = kas.derive_key(keylen,
- pubkey).bits_of();
+ secure_vector<byte> got = kas.derive_key(keylen,
+ pubkey).bits_of();
if(got != expected)
{
std::cout << "FAILED: " << algo << std::endl;
- dump_data(got, expected);
+ dump_data(unlock(got), unlock(expected));
failure = true;
}
}
@@ -247,7 +253,7 @@ u32bit validate_rsa_enc_pkcs8(const std::string& algo,
DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
str[0].length());
- std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
+ std::unique_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
RSA_PrivateKey* rsapriv = dynamic_cast<RSA_PrivateKey*>(privkey.get());
if(!rsapriv)
@@ -319,8 +325,8 @@ u32bit validate_elg_enc(const std::string& algo,
validate_encryption(e, d, algo, str[4], str[5], str[6], failure);
}
else
- validate_decryption(d, algo, hex_decode(str[5]),
- hex_decode(str[4]), failure);
+ validate_decryption(d, algo, unlock(hex_decode(str[5])),
+ unlock(hex_decode(str[4])), failure);
return (failure ? 1 : 0);
#endif
@@ -367,8 +373,8 @@ u32bit validate_rsa_ver(const std::string& algo,
PK_Verifier v(key, emsa);
- SecureVector<byte> msg = hex_decode(str[2]);
- SecureVector<byte> sig = hex_decode(str[3]);
+ std::vector<byte> msg = unlock(hex_decode(str[2]));
+ std::vector<byte> sig = unlock(hex_decode(str[3]));
bool passed = true;
passed = v.verify_message(msg, sig);
@@ -388,7 +394,7 @@ u32bit validate_rsa_ver_x509(const std::string& algo,
DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
str[0].length());
- std::auto_ptr<Public_Key> key(X509::load_key(keysource));
+ std::unique_ptr<Public_Key> key(X509::load_key(keysource));
RSA_PublicKey* rsakey = dynamic_cast<RSA_PublicKey*>(key.get());
@@ -399,8 +405,8 @@ u32bit validate_rsa_ver_x509(const std::string& algo,
PK_Verifier v(*rsakey, emsa);
- SecureVector<byte> msg = hex_decode(str[1]);
- SecureVector<byte> sig = hex_decode(str[2]);
+ std::vector<byte> msg = unlock(hex_decode(str[1]));
+ std::vector<byte> sig = unlock(hex_decode(str[2]));
bool passed = v.verify_message(msg, sig);
return (passed ? 0 : 1);
@@ -423,8 +429,8 @@ u32bit validate_rw_ver(const std::string& algo,
PK_Verifier v(key, emsa);
- SecureVector<byte> msg = hex_decode(str[2]);
- SecureVector<byte> sig = hex_decode(str[3]);
+ std::vector<byte> msg = unlock(hex_decode(str[2]));
+ std::vector<byte> sig = unlock(hex_decode(str[3]));
bool passed = true;
passed = v.verify_message(msg, sig);
@@ -476,7 +482,7 @@ u32bit validate_dsa_sig(const std::string& algo,
DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
str[0].length());
- std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
+ std::unique_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
DSA_PrivateKey* dsapriv = dynamic_cast<DSA_PrivateKey*>(privkey.get());
if(!dsapriv)
@@ -532,7 +538,7 @@ u32bit validate_gost_ver(const std::string& algo,
EC_Group group(OIDS::lookup(str[0]));
- PointGFp public_point = OS2ECP(hex_decode(str[1]), group.get_curve());
+ PointGFp public_point = OS2ECP(unlock(hex_decode(str[1])), group.get_curve());
GOST_3410_PublicKey gost(group, public_point);
@@ -540,8 +546,8 @@ u32bit validate_gost_ver(const std::string& algo,
PK_Verifier v(gost, emsa);
- SecureVector<byte> msg = hex_decode(str[2]);
- SecureVector<byte> sig = hex_decode(str[3]);
+ std::vector<byte> msg = unlock(hex_decode(str[2]));
+ std::vector<byte> sig = unlock(hex_decode(str[3]));
bool passed = v.verify_message(msg, sig);
return (passed ? 0 : 1);
@@ -561,7 +567,7 @@ u32bit validate_dsa_ver(const std::string& algo,
#if defined(BOTAN_HAS_DSA)
- std::auto_ptr<Public_Key> key(X509::load_key(keysource));
+ std::unique_ptr<Public_Key> key(X509::load_key(keysource));
DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get());
@@ -572,8 +578,8 @@ u32bit validate_dsa_ver(const std::string& algo,
PK_Verifier v(*dsakey, emsa);
- SecureVector<byte> msg = hex_decode(str[1]);
- SecureVector<byte> sig = hex_decode(str[2]);
+ std::vector<byte> msg = unlock(hex_decode(str[1]));
+ std::vector<byte> sig = unlock(hex_decode(str[2]));
v.set_input_format(DER_SEQUENCE);
bool passed = v.verify_message(msg, sig);
diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp
index de8ad0730..da2221b90 100644
--- a/checks/pk_bench.cpp
+++ b/checks/pk_bench.cpp
@@ -10,6 +10,12 @@
#include <botan/oids.h>
#include <map>
+#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
+ #include <botan/x509_key.h>
+ #include <botan/pkcs8.h>
+ #include <botan/pubkey.h>
+#endif
+
#if defined(BOTAN_HAS_RSA)
#include <botan/rsa.h>
#endif
@@ -77,7 +83,7 @@ const char* ec_domains[] = {
"secp256r1",
"secp384r1",
"secp521r1",
- 0
+ nullptr
};
class Benchmark_Report
@@ -98,7 +104,7 @@ void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec,
RandomNumberGenerator& rng,
u32bit runs, double seconds)
{
- SecureVector<byte> plaintext, ciphertext;
+ std::vector<byte> plaintext, ciphertext;
for(u32bit i = 0; i != runs; ++i)
{
@@ -121,7 +127,7 @@ void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec,
if(dec_timer.seconds() < seconds)
{
dec_timer.start();
- SecureVector<byte> plaintext_out = dec.decrypt(ciphertext);
+ std::vector<byte> plaintext_out = unlock(dec.decrypt(ciphertext));
dec_timer.stop();
if(plaintext_out != plaintext)
@@ -137,7 +143,7 @@ void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig,
RandomNumberGenerator& rng,
u32bit runs, double seconds)
{
- SecureVector<byte> message, signature, sig_random;
+ std::vector<byte> message, signature, sig_random;
for(u32bit i = 0; i != runs; ++i)
{
@@ -165,7 +171,7 @@ void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig,
if((i % 100) == 0)
{
- sig_random = rng.random_vec(signature.size());
+ sig_random = unlock(rng.random_vec(signature.size()));
verify_timer.start();
const bool verified_bad = ver.verify_message(message, sig_random);
@@ -240,7 +246,7 @@ void benchmark_rsa(RandomNumberGenerator& rng,
sig_timer, rng, 10000, seconds);
}
- const std::string rsa_keylen = "RSA-" + to_string(keylen);
+ const std::string rsa_keylen = "RSA-" + std::to_string(keylen);
report.report(rsa_keylen, keygen_timer);
report.report(rsa_keylen, verify_timer);
@@ -292,7 +298,7 @@ void benchmark_rw(RandomNumberGenerator& rng,
rng, 10000, seconds);
}
- const std::string nm = "RW-" + to_string(keylen);
+ const std::string nm = "RW-" + std::to_string(keylen);
report.report(nm, keygen_timer);
report.report(nm, verify_timer);
report.report(nm, sig_timer);
@@ -319,7 +325,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng,
if(hashbits == 521)
hashbits = 512;
- const std::string padding = "EMSA1(SHA-" + to_string(hashbits) + ")";
+ const std::string padding = "EMSA1(SHA-" + std::to_string(hashbits) + ")";
Timer keygen_timer("keygen");
Timer verify_timer(padding + " verify");
@@ -339,7 +345,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng,
sig_timer, rng, 1000, seconds);
}
- const std::string nm = "ECDSA-" + to_string(pbits);
+ const std::string nm = "ECDSA-" + std::to_string(pbits);
report.report(nm, keygen_timer);
report.report(nm, verify_timer);
@@ -381,7 +387,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng,
sig_timer, rng, 1000, seconds);
}
- const std::string nm = "GOST-34.10-" + to_string(pbits);
+ const std::string nm = "GOST-34.10-" + std::to_string(pbits);
report.report(nm, keygen_timer);
report.report(nm, verify_timer);
@@ -439,7 +445,7 @@ void benchmark_ecdh(RandomNumberGenerator& rng,
}
}
- const std::string nm = "ECDH-" + to_string(pbits);
+ const std::string nm = "ECDH-" + std::to_string(pbits);
report.report(nm, keygen_timer);
report.report(nm, kex_timer);
}
@@ -456,7 +462,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng,
const char* domains[] = { "dsa/jce/1024",
"dsa/botan/2048",
"dsa/botan/3072",
- NULL };
+ nullptr };
std::string algo_name;
@@ -465,7 +471,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng,
size_t pbits = to_u32bit(split_on(domains[j], '/')[2]);
size_t qbits = (pbits <= 1024) ? 160 : 256;
- const std::string padding = "EMSA1(SHA-" + to_string(qbits) + ")";
+ const std::string padding = "EMSA1(SHA-" + std::to_string(qbits) + ")";
Timer keygen_timer("keygen");
Timer verify_timer(padding + " verify");
@@ -488,7 +494,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng,
sig_timer, rng, 1000, seconds);
}
- const std::string nm = algo_name + "-" + to_string(pbits);
+ const std::string nm = algo_name + "-" + std::to_string(pbits);
report.report(nm, keygen_timer);
report.report(nm, verify_timer);
report.report(nm, sig_timer);
@@ -507,7 +513,7 @@ void benchmark_dh(RandomNumberGenerator& rng,
"modp/ietf/4096",
"modp/ietf/6144",
"modp/ietf/8192",
- NULL };
+ nullptr };
for(size_t j = 0; domains[j]; j++)
{
@@ -568,7 +574,7 @@ void benchmark_dlies(RandomNumberGenerator& rng,
"modp/ietf/4096",
"modp/ietf/6144",
"modp/ietf/8192",
- NULL };
+ nullptr };
for(size_t j = 0; domains[j]; j++)
{
@@ -627,7 +633,7 @@ void benchmark_elg(RandomNumberGenerator& rng,
"modp/ietf/4096",
"modp/ietf/6144",
"modp/ietf/8192",
- NULL };
+ nullptr };
const std::string algo_name = "ElGamal";
@@ -657,7 +663,7 @@ void benchmark_elg(RandomNumberGenerator& rng,
rng, 1000, seconds);
}
- const std::string nm = algo_name + "-" + to_string(pbits);
+ const std::string nm = algo_name + "-" + std::to_string(pbits);
report.report(nm, keygen_timer);
report.report(nm, enc_timer);
report.report(nm, dec_timer);
diff --git a/checks/timer.cpp b/checks/timer.cpp
index 3736a4779..9f3d34607 100644
--- a/checks/timer.cpp
+++ b/checks/timer.cpp
@@ -5,7 +5,7 @@
*/
#include "timer.h"
-#include <botan/time.h>
+#include <chrono>
#include <iomanip>
Timer::Timer(const std::string& n, u32bit e_mul) :
@@ -38,7 +38,8 @@ void Timer::stop()
u64bit Timer::get_clock()
{
- return Botan::get_nanoseconds_clock();
+ auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
}
std::ostream& operator<<(std::ostream& out, Timer& timer)
diff --git a/checks/validate.cpp b/checks/validate.cpp
index 65317604e..bae5e857f 100644
--- a/checks/validate.cpp
+++ b/checks/validate.cpp
@@ -110,6 +110,7 @@ bool keywrap_test(const char* key_str,
bool ok = true;
+#if defined(BOTAN_HAS_RFC3394_KEYWRAP)
try
{
SymmetricKey key(key_str);
@@ -118,7 +119,7 @@ bool keywrap_test(const char* key_str,
Algorithm_Factory& af = global_state().algorithm_factory();
- SecureVector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af);
+ secure_vector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af);
if(enc != expected.bits_of())
{
@@ -127,7 +128,7 @@ bool keywrap_test(const char* key_str,
ok = false;
}
- SecureVector<byte> dec = rfc3394_keyunwrap(expected.bits_of(), kek, af);
+ secure_vector<byte> dec = rfc3394_keyunwrap(expected.bits_of(), kek, af);
if(dec != key.bits_of())
{
@@ -140,6 +141,7 @@ bool keywrap_test(const char* key_str,
{
std::cout << e.what() << "\n";
}
+#endif
return ok;
}
@@ -339,7 +341,7 @@ u32bit do_validation_tests(const std::string& filename,
if(should_pass)
std::cout << "Testing " << algorithm << "..." << std::endl;
else
- std::cout << "Testing (expecing failure) "
+ std::cout << "Testing (expecting failure) "
<< algorithm << "..." << std::endl;
#endif
alg_count = 0;
@@ -472,8 +474,10 @@ bool failed_test(const std::string& algo,
try {
Botan::Filter* test = lookup(algo, params);
- if(test == 0 && is_extension) return !exp_pass;
- if(test == 0)
+
+ if(!test && is_extension) return !exp_pass;
+
+ if(!test)
{
if(algo != last_missing)
{
@@ -488,7 +492,7 @@ bool failed_test(const std::string& algo,
pipe.append(test);
pipe.append(new Botan::Hex_Encoder);
- Botan::SecureVector<byte> data = Botan::hex_decode(in);
+ secure_vector<byte> data = Botan::hex_decode(in);
const byte* data_ptr = &data[0];
// this can help catch errors with buffering, etc
@@ -536,7 +540,7 @@ bool failed_test(const std::string& algo,
size_t offset = random_word(rng, pipe.remaining() - 1);
size_t length = random_word(rng, pipe.remaining() - offset);
- Botan::SecureVector<byte> peekbuf(length);
+ std::vector<byte> peekbuf(length);
pipe.peek(&peekbuf[0], peekbuf.size(), offset);
output = pipe.read_all_as_string();
diff --git a/checks/validate.dat b/checks/validate.dat
index 6b9a49e52..7b221db49 100644
--- a/checks/validate.dat
+++ b/checks/validate.dat
@@ -4123,25 +4123,64 @@ F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566
FEDCBA9876543210:05044B62FA52D080:\
F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677
-[Camellia]
+[Camellia-128]
# From RFC 3713
-
0123456789ABCDEFFEDCBA9876543210:67673138549669730857065648EABE43:\
0123456789ABCDEFFEDCBA9876543210
+# Nessie
+00000000000000000000000000000000:6C227F749319A3AA7DA235A9BBA05A2C:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:F04D51E45E70FB6DEE0D16A204FBBA16:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:ED44242E619F8C32EAA2D3641DA47EA4:\
+20000000000000000000000000000000
+
+EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF:5CA8B8A4B8AF15A6184259831B18BBB5:\
+EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF
+
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:25DD9EB9DD67FBC6E8431F56F4FBE651:\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+
+[Camellia-192]
+# From RFC 3713
0123456789ABCDEFFEDCBA9876543210:B4993401B3E996F84EE5CEE7D79B09B9:\
0123456789ABCDEFFEDCBA98765432100011223344556677
+# Nessie
+
+00000000000000000000000000000000:1B6220D365C2176C1D41A5826520FCA1:\
+800000000000000000000000000000000000000000000000
+
+FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE:A2F5A98929658AF4A9700B9923DAF014:\
+FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE
+
+[Camellia-256]
+# From RFC 3713
0123456789ABCDEFFEDCBA9876543210:9ACC237DFF16D76C20EF7C919E3A7509:\
0123456789ABCDEFFEDCBA987654321000112233445566778899AABBCCDDEEFF
-# From NESSIE
+00000000000000000000000000000000:2136FABDA091DFB5171B94B8EFBB5D08:\
+8000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000:6C227F749319A3AA7DA235A9BBA05A2C:\
-80000000000000000000000000000000
+00000000000000000000000000000000:E18B0CB1980124504B46A46A6F4273F3:\
+0000000000000200000000000000000000000000000000000000000000000000
-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:25DD9EB9DD67FBC6E8431F56F4FBE651:\
-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+00000000000000000000000000000001:9CDB269B5D293BC5DB9C55B057D9B591:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0000000000000000000000000000000000000000000000000000000000000001\
+0000000000000000000000000000000200000000000000000000000000000004\
+0000000000000000000000000000000800000000000000000000000000000010\
+0000000000000000000000000000002000000000000000000000000000000040:\
+396154111ADEFC500CF6E5C99038BC179CDB269B5D293BC5DB9C55B057D9B591\
+3D4B2CDE666761BA5DFB305178E667FB6A3F25AAB7E92D9CF378E5D9C040F26B\
+7C92854D801A1648F65CA81813DDBF83BA664AC39855518DFDEE10D1B3111FAE\
+7A6985778D3A66E97F23E01F0D0E45E78B1F247802E47C91BEE2AA34ECFD7A01:\
+0000000000000000000000000000000000000000000000000000000000000000
# First one is from RFC 2144. The rest were done with OpenSSL and bits taken
# from /dev/urandom
@@ -67685,6 +67724,8 @@ DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E\
[Parallel(MD5,SHA-1)]
:D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+61:0CC175B9C0F1B6A831C399E26977266186F7E437FAA5A7FCE15D1DDCB9EAEAEA377667B8
+
[Parallel(SHA-160,Tiger(24,3))]
:DA39A3EE5E6B4B0D3255BFEF95601890AFD807093293AC630\
C13F0245F92BBB1766E16167A4E58492DDE73F3
diff --git a/checks/x509.cpp b/checks/x509.cpp
index 138d1b346..46b748da6 100644
--- a/checks/x509.cpp
+++ b/checks/x509.cpp
@@ -49,7 +49,7 @@ u64bit key_id(const Public_Key* key)
pipe.write(key->x509_subject_public_key());
pipe.end_msg();
- SecureVector<byte> output = pipe.read_all();
+ secure_vector<byte> output = pipe.read_all();
if(output.size() != 8)
throw Internal_Error("Public_Key::key_id: Incorrect output size");
@@ -147,7 +147,6 @@ void do_x509_tests(RandomNumberGenerator& rng)
std::cout << '.' << std::flush;
/* Create user #1's key and cert request */
- std::cout << '.' << std::flush;
DSA_PrivateKey user1_key(rng, DL_Group("dsa/botan/2048"));
std::cout << '.' << std::flush;
diff --git a/configure.py b/configure.py
index 71d2a3d39..31b55756d 100755
--- a/configure.py
+++ b/configure.py
@@ -2,7 +2,7 @@
"""
Configuration program for botan (http://botan.randombit.net/)
- (C) 2009-2011 Jack Lloyd
+ (C) 2009,2010,2011,2012 Jack Lloyd
Distributed under the terms of the Botan license
Tested with CPython 2.6, 2.7, 3.1 and PyPy 1.5
@@ -267,10 +267,6 @@ def process_command_line(args):
default=False, action='store_true',
help='build via amalgamation')
- build_group.add_option('--with-tr1-implementation', metavar='WHICH',
- dest='with_tr1', default=None,
- help='enable TR1 (choices: none, system, boost)')
-
build_group.add_option('--with-build-dir',
metavar='DIR', default='',
help='setup the build in DIR')
@@ -306,10 +302,6 @@ def process_command_line(args):
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=optparse.SUPPRESS_HELP)
-
build_group.add_option('--maintainer-mode', dest='maintainer_mode',
action='store_true', default=False,
help=optparse.SUPPRESS_HELP)
@@ -548,7 +540,6 @@ class ModuleInfo(object):
{
'load_on': 'auto',
'define': [],
- 'uses_tr1': 'false',
'need_isa': None,
'mp_bits': 0 })
@@ -597,8 +588,6 @@ class ModuleInfo(object):
self.mp_bits = int(self.mp_bits)
- self.uses_tr1 = (True if self.uses_tr1 == 'yes' else False)
-
if self.comment != []:
self.comment = ' '.join(self.comment)
else:
@@ -643,12 +632,6 @@ class ModuleInfo(object):
def compatible_compiler(self, cc):
return self.cc == [] or cc in self.cc
- def tr1_ok(self, with_tr1):
- if self.uses_tr1:
- return with_tr1 in ['boost', 'system']
- else:
- return True
-
def dependencies(self):
# utils is an implicit dep (contains types, etc)
deps = self.requires + ['utils']
@@ -776,8 +759,7 @@ class CompilerInfo(object):
'visibility_build_flags': '',
'visibility_attribute': '',
'ar_command': None,
- 'makefile_style': '',
- 'has_tr1': False,
+ 'makefile_style': ''
})
self.so_link_flags = force_to_dict(self.so_link_flags)
@@ -884,19 +866,8 @@ class CompilerInfo(object):
"""
Return defines for build.h
"""
- def defines(self, with_tr1):
-
- def tr1_macro():
- if with_tr1:
- if with_tr1 == 'boost':
- return ['USE_BOOST_TR1']
- elif with_tr1 == 'system':
- return ['USE_STD_TR1']
- elif self.has_tr1:
- return ['USE_STD_TR1']
- return []
-
- return ['BUILD_COMPILER_IS_' + self.macro_name] + tr1_macro()
+ def defines(self):
+ return ['BUILD_COMPILER_IS_' + self.macro_name]
class OsInfo(object):
def __init__(self, infofile):
@@ -1035,10 +1006,15 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
if dir.startswith('src'):
parts = dir.split(os.sep)[1:]
+
+ # Handle src/X/X.cpp -> X.o
if file == parts[-1] + '.cpp':
name = '_'.join(dir.split(os.sep)[1:]) + '.cpp'
else:
name = '_'.join(dir.split(os.sep)[1:]) + '_' + file
+
+ # Special case hack cause I'm lazy
+ name = name.replace('tls_tls_', 'tls_')
else:
name = file
@@ -1137,7 +1113,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'lib_opt': cc.library_opt_flags(options),
'mach_opt': cc.mach_opts(options.arch, options.cpu),
'check_opt': '' if options.no_optimizations else cc.check_opt_flags,
- 'lang_flags': cc.lang_flags + options.extra_flags,
+ 'lang_flags': cc.lang_flags,
'warn_flags': warning_flags(cc.warning_flags,
cc.maintainer_warning_flags,
options.maintainer_mode),
@@ -1153,8 +1129,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'target_os_defines': make_cpp_macros(osinfo.defines()),
- 'target_compiler_defines': make_cpp_macros(
- cc.defines(options.with_tr1)),
+ 'target_compiler_defines': make_cpp_macros(cc.defines()),
'target_cpu_defines': make_cpp_macros(arch.defines(options)),
@@ -1245,8 +1220,6 @@ def choose_modules_to_use(modules, archinfo, options):
cannot_use_because(modname, 'incompatible compiler')
elif not module.compatible_cpu(archinfo, options):
cannot_use_because(modname, 'incompatible CPU')
- elif not module.tr1_ok(options.with_tr1):
- cannot_use_because(modname, 'missing TR1')
else:
if module.load_on == 'never':
@@ -1760,7 +1733,6 @@ def main(argv = None):
cc = ccinfo[options.compiler]
# Kind of a hack...
- options.extra_flags = ''
if options.compiler == 'gcc':
def get_gcc_version(gcc_bin):
@@ -1785,49 +1757,17 @@ def main(argv = None):
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
-
gcc_version = get_gcc_version(options.compiler_binary or cc.binary_name)
if gcc_version:
+ versions_without_cpp0x = '(4\.[01234]\.)|(3\.[0-4]\.)|(2\.95\.[0-4])'
- 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
-
- 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 re.search(versions_without_cpp0x, gcc_version):
+ logging.info('This GCC is too old to compile C++0x')
if options.with_visibility is None:
options.with_visibility = True
- if options.with_tr1 == None:
- if cc.has_tr1:
- logging.info('Assuming %s has TR1 (use --with-tr1=none to disable)' % (
- options.compiler))
- options.with_tr1 = 'system'
- else:
- options.with_tr1 = 'none'
-
if options.with_sphinx is None:
if have_program('sphinx-build'):
logging.info('Found sphinx-build, will use it ' +
diff --git a/doc/contents.txt b/doc/contents.txt
index dd600d587..141c9188f 100644
--- a/doc/contents.txt
+++ b/doc/contents.txt
@@ -12,7 +12,8 @@ Contents
filters
pubkey
x509
- ssl
+ tls
+ credentials_manager
bigint
lowlevel
secmem
diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile
index a5da47a7c..b034cac78 100644
--- a/doc/examples/GNUmakefile
+++ b/doc/examples/GNUmakefile
@@ -1,9 +1,9 @@
BOTAN_CONFIG = botan-config
-CXX = g++
-CFLAGS = -O2 -ansi -W -Wall -I../../build/include
-LIBS = -L../.. -lbotan-1.10
+CXX = g++-4.8.0-r187608
+CFLAGS = -O2 -ansi -std=c++0x -W -Wall -I../../build/include
+LIBS = -L../.. -lbotan-1.99
SRCS=$(wildcard *.cpp)
@@ -19,3 +19,6 @@ clean:
eax_test: eax_test.cpp
$(CXX) $(CFLAGS) $? $(LIBS) -lboost_regex -o $@
+
+asio_tls_server: asio_tls_server.cpp credentials.h
+ $(CXX) $(CFLAGS) $< $(LIBS) -lboost_thread -lboost_system -o $@
diff --git a/doc/examples/asio_tls_server.cpp b/doc/examples/asio_tls_server.cpp
new file mode 100644
index 000000000..0cf499e0a
--- /dev/null
+++ b/doc/examples/asio_tls_server.cpp
@@ -0,0 +1,295 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#define _GLIBCXX_HAVE_GTHR_DEFAULT
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include <botan/tls_server.h>
+#include <botan/x509cert.h>
+#include <botan/pkcs8.h>
+#include <botan/auto_rng.h>
+#include <botan/init.h>
+
+#include "credentials.h"
+
+using Botan::byte;
+using boost::asio::ip::tcp;
+
+class tls_server_session : public boost::enable_shared_from_this<tls_server_session>
+ {
+ public:
+ typedef boost::shared_ptr<tls_server_session> pointer;
+
+ static pointer create(boost::asio::io_service& io_service,
+ Botan::TLS::Session_Manager& session_manager,
+ Botan::Credentials_Manager& credentials,
+ Botan::TLS::Policy& policy,
+ Botan::RandomNumberGenerator& rng)
+ {
+ return pointer(
+ new tls_server_session(
+ io_service,
+ session_manager,
+ credentials,
+ policy,
+ rng)
+ );
+ }
+
+ tcp::socket& socket() { return m_socket; }
+
+ void start()
+ {
+ m_socket.async_read_some(
+ boost::asio::buffer(m_read_buf, sizeof(m_read_buf)),
+ m_strand.wrap(
+ boost::bind(&tls_server_session::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred)));
+ }
+
+ void stop() { m_socket.close(); }
+
+ private:
+ tls_server_session(boost::asio::io_service& io_service,
+ Botan::TLS::Session_Manager& session_manager,
+ Botan::Credentials_Manager& credentials,
+ Botan::TLS::Policy& policy,
+ Botan::RandomNumberGenerator& rng) :
+ m_strand(io_service),
+ m_socket(io_service),
+ m_tls(boost::bind(&tls_server_session::tls_output_wanted, this, _1, _2),
+ boost::bind(&tls_server_session::tls_data_recv, this, _1, _2, _3),
+ boost::bind(&tls_server_session::tls_handshake_complete, this, _1),
+ session_manager,
+ credentials,
+ policy,
+ rng)
+ {
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if(!error)
+ {
+ try
+ {
+ m_tls.received_data(m_read_buf, bytes_transferred);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Read failed " << e.what() << "\n";
+ stop();
+ return;
+ }
+
+ m_socket.async_read_some(
+ boost::asio::buffer(m_read_buf, sizeof(m_read_buf)),
+ m_strand.wrap(boost::bind(&tls_server_session::handle_read, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred)));
+ }
+ else
+ {
+ stop();
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if(!error)
+ {
+ m_write_buf.clear();
+
+ // initiate another write if needed
+ tls_output_wanted(NULL, 0);
+ }
+ else
+ {
+ stop();
+ }
+ }
+
+ void tls_output_wanted(const byte buf[], size_t buf_len)
+ {
+ if(buf_len > 0)
+ m_outbox.insert(m_outbox.end(), buf, buf + buf_len);
+
+ // no write pending and have output pending
+ if(m_write_buf.empty() && !m_outbox.empty())
+ {
+ std::swap(m_outbox, m_write_buf);
+
+ boost::asio::async_write(m_socket,
+ boost::asio::buffer(&m_write_buf[0], m_write_buf.size()),
+ m_strand.wrap(
+ boost::bind(&tls_server_session::handle_write,
+ shared_from_this(),
+ boost::asio::placeholders::error)));
+ }
+ }
+
+ void tls_data_recv(const byte buf[], size_t buf_len, Botan::TLS::Alert alert)
+ {
+ if(alert.is_valid())
+ {
+ if(alert.type() == Botan::TLS::Alert::CLOSE_NOTIFY)
+ {
+ m_tls.close();
+ return;
+ }
+ }
+
+ if(buf_len > 4) // FIXME: ghetto
+ {
+ std::string out;
+ out += "\r\n";
+ out += "HTTP/1.0 200 OK\r\n";
+ out += "Server: Botan ASIO test server\r\n";
+ if(m_hostname != "")
+ out += "Host: " + m_hostname + "\r\n";
+ out += "Content-Type: text/html\r\n";
+ out += "\r\n";
+ out += "<html><body>Greets. You said: ";
+ out += std::string((const char*)buf, buf_len);
+ out += "</body></html>\r\n\r\n";
+
+ m_tls.send(reinterpret_cast<const byte*>(&out[0]),
+ out.size());
+ m_tls.close();
+ }
+ }
+
+ bool tls_handshake_complete(const Botan::TLS::Session& session)
+ {
+ m_hostname = session.sni_hostname();
+ return true;
+ }
+
+ boost::asio::io_service::strand m_strand; // serialization
+
+ tcp::socket m_socket;
+ Botan::TLS::Server m_tls;
+ std::string m_hostname;
+
+ unsigned char m_read_buf[Botan::TLS::MAX_TLS_RECORD_SIZE];
+
+ // used to hold the data currently being written by the system
+ std::vector<byte> m_write_buf;
+
+ // used to hold data queued for writing
+ std::vector<byte> m_outbox;
+ };
+
+class tls_server
+ {
+ public:
+ typedef tls_server_session session;
+
+ tls_server(boost::asio::io_service& io_service, unsigned short port) :
+ m_acceptor(io_service, tcp::endpoint(tcp::v4(), port)),
+ m_creds(m_rng)
+ {
+ session::pointer new_session = make_session();
+
+ m_acceptor.async_accept(
+ new_session->socket(),
+ boost::bind(
+ &tls_server::handle_accept,
+ this,
+ new_session,
+ boost::asio::placeholders::error)
+ );
+ }
+
+ private:
+ session::pointer make_session()
+ {
+ return session::create(
+ m_acceptor.get_io_service(),
+ m_session_manager,
+ m_creds,
+ m_policy,
+ m_rng
+ );
+ }
+
+ void handle_accept(session::pointer new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+
+ new_session = make_session();
+
+ m_acceptor.async_accept(
+ new_session->socket(),
+ boost::bind(
+ &tls_server::handle_accept,
+ this,
+ new_session,
+ boost::asio::placeholders::error)
+ );
+ }
+ }
+
+ tcp::acceptor m_acceptor;
+
+ Botan::AutoSeeded_RNG m_rng;
+ Botan::TLS::Session_Manager_In_Memory m_session_manager;
+ Botan::TLS::Policy m_policy;
+ Credentials_Manager_Simple m_creds;
+ };
+
+size_t choose_thread_count()
+ {
+ size_t result = boost::thread::hardware_concurrency();
+
+ if(result)
+ return result;
+
+ return 2;
+ }
+
+int main()
+ {
+ try
+ {
+ Botan::LibraryInitializer init("thread_safe=true");
+ boost::asio::io_service io_service;
+
+ unsigned short port = 4434;
+ tls_server server(io_service, port);
+
+ const size_t num_threads = choose_thread_count();
+
+ std::cout << "Using " << num_threads << " threads\n";
+
+ std::vector<boost::shared_ptr<boost::thread> > threads;
+
+ for(size_t i = 0; i != num_threads; ++i)
+ {
+ boost::shared_ptr<boost::thread> thread(
+ new boost::thread(
+ boost::bind(&boost::asio::io_service::run, &io_service)));
+ threads.push_back(thread);
+ }
+
+ // Wait for all threads in the pool to exit.
+ for (size_t i = 0; i < threads.size(); ++i)
+ threads[i]->join();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+ }
+
diff --git a/doc/examples/asn1.cpp b/doc/examples/asn1.cpp
index 95e5b2627..d12ee1eec 100644
--- a/doc/examples/asn1.cpp
+++ b/doc/examples/asn1.cpp
@@ -72,8 +72,8 @@ void decode(BER_Decoder& decoder, size_t level)
/* hack to insert the tag+length back in front of the stuff now
that we've gotten the type info */
DER_Encoder encoder;
- encoder.add_object(type_tag, class_tag, obj.value, obj.value.size());
- SecureVector<byte> bits = encoder.get_contents();
+ encoder.add_object(type_tag, class_tag, obj.value);
+ secure_vector<byte> bits = encoder.get_contents();
BER_Decoder data(bits);
@@ -97,7 +97,7 @@ void decode(BER_Decoder& decoder, size_t level)
if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC) ||
(class_tag & PRIVATE))
{
- name = "cons [" + to_string(type_tag) + "]";
+ name = "cons [" + std::to_string(type_tag) + "]";
if(class_tag & APPLICATION)
name += " appl";
@@ -124,7 +124,7 @@ void decode(BER_Decoder& decoder, size_t level)
Pipe pipe(((not_text) ? new Hex_Encoder : 0));
pipe.process_msg(bits);
- emit("[" + to_string(type_tag) + "]", level, length,
+ emit("[" + std::to_string(type_tag) + "]", level, length,
pipe.read_all_as_string());
}
else if(type_tag == OBJECT_ID)
@@ -143,7 +143,7 @@ void decode(BER_Decoder& decoder, size_t level)
BigInt number;
data.decode(number);
- SecureVector<byte> rep;
+ std::vector<byte> rep;
/* If it's small, it's probably a number, not a hash */
if(number.bits() <= 16)
@@ -170,7 +170,7 @@ void decode(BER_Decoder& decoder, size_t level)
}
else if(type_tag == OCTET_STRING)
{
- SecureVector<byte> bits;
+ secure_vector<byte> bits;
data.decode(bits, type_tag);
bool not_text = false;
@@ -184,7 +184,7 @@ void decode(BER_Decoder& decoder, size_t level)
}
else if(type_tag == BIT_STRING)
{
- SecureVector<byte> bits;
+ secure_vector<byte> bits;
data.decode(bits, type_tag);
std::vector<bool> bit_set;
diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp
index 6cfd9205f..5378b3e6a 100644
--- a/doc/examples/bench.cpp
+++ b/doc/examples/bench.cpp
@@ -67,22 +67,19 @@ const std::string algos[] = {
"",
};
+
void benchmark_algo(const std::string& algo,
RandomNumberGenerator& rng)
{
- u32bit milliseconds = 1000;
+ std::chrono::milliseconds ms(1000);
Algorithm_Factory& af = global_state().algorithm_factory();
- std::map<std::string, double> speeds =
- algorithm_benchmark(algo, af, rng, milliseconds, 16);
+ auto speeds = algorithm_benchmark(algo, af, rng, ms, 16);
std::cout << algo << ":";
- for(std::map<std::string, double>::const_iterator i = speeds.begin();
- i != speeds.end(); ++i)
- {
- std::cout << " " << i->second << " [" << i->first << "]";
- }
+ for(auto s: speeds)
+ std::cout << " " << s.second << " [" << s.first << "]";
std::cout << "\n";
}
@@ -96,12 +93,12 @@ int main(int argc, char* argv[])
if(argc == 1) // no args, benchmark everything
{
- for(u32bit i = 0; algos[i] != ""; ++i)
+ for(size_t i = 0; algos[i] != ""; ++i)
benchmark_algo(algos[i], rng);
}
else
{
- for(int i = 1; argv[i]; ++i)
+ for(size_t i = 1; argv[i]; ++i)
benchmark_algo(argv[i], rng);
}
}
diff --git a/doc/examples/benchmark.cpp b/doc/examples/benchmark.cpp
index b5adb3d4f..a11054c0c 100644
--- a/doc/examples/benchmark.cpp
+++ b/doc/examples/benchmark.cpp
@@ -26,14 +26,13 @@ int main(int argc, char* argv[])
Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
- double ms = 1000 * std::atof(argv[1]);
+ std::chrono::milliseconds ms(static_cast<std::chrono::milliseconds::rep>(1000 * std::atof(argv[1])));
for(size_t i = 2; argv[i]; ++i)
{
std::string algo = argv[i];
- std::map<std::string, double> results =
- algorithm_benchmark(algo, af, rng, ms, 16);
+ auto results = algorithm_benchmark(algo, af, rng, ms, 16);
std::cout << algo << ":\n";
for(std::map<std::string, double>::iterator r = results.begin();
diff --git a/doc/examples/bzip.cpp b/doc/examples/bzip.cpp
index 6137bb6af..74ba431ed 100644
--- a/doc/examples/bzip.cpp
+++ b/doc/examples/bzip.cpp
@@ -37,6 +37,7 @@ int main(int argc, char* argv[])
Botan::LibraryInitializer init;
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
std::vector<std::string> files;
bool decompress = false, small = false;
int level = 9;
@@ -60,18 +61,10 @@ int main(int argc, char* argv[])
try {
Botan::Filter* bzip = 0;
-#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
if(decompress)
bzip = new Botan::Bzip_Decompression(small);
else
bzip = new Botan::Bzip_Compression(level);
-#endif
-
- if(!bzip)
- {
- std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
- return 1;
- }
Botan::Pipe pipe(bzip);
@@ -112,5 +105,11 @@ int main(int argc, char* argv[])
std::cout << "Exception caught: " << e.what() << std::endl;
return 1;
}
+#else
+
+ std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
+
+#endif
+
return 0;
}
diff --git a/doc/examples/ca.cpp b/doc/examples/ca.cpp
index 7a3e6daf9..6fd2eb15b 100644
--- a/doc/examples/ca.cpp
+++ b/doc/examples/ca.cpp
@@ -1,10 +1,10 @@
#include <botan/botan.h>
#include <botan/x509_ca.h>
-#include <botan/time.h>
using namespace Botan;
#include <iostream>
#include <memory>
+#include <chrono>
int main(int argc, char* argv[])
{
@@ -41,8 +41,13 @@ int main(int argc, char* argv[])
// (this example should be extended to show how)
// now sign the request
- X509_Time start_time(system_time());
- X509_Time end_time(system_time() + 365 * 60 * 60 * 24);
+ auto now = std::chrono::system_clock::now();
+
+ X509_Time start_time(now);
+
+ typedef std::chrono::duration<int, std::ratio<31556926>> years;
+
+ X509_Time end_time(now + years(1));
X509_Certificate new_cert = ca.sign_request(req, rng,
start_time, end_time);
diff --git a/doc/examples/cms_dec.cpp b/doc/examples/cms_dec.cpp
deleted file mode 100644
index 84355fb4a..000000000
--- a/doc/examples/cms_dec.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/botan.h>
-#include <botan/pkcs8.h>
-#include <botan/cms_dec.h>
-using namespace Botan;
-
-#include <iostream>
-#include <memory>
-
-int main(int argc, char* argv[])
- {
- if(argc != 2)
- {
- std::cout << "Usage: " << argv[0] << " <filename>\n";
- return 1;
- }
-
- Botan::LibraryInitializer init;
-
- try {
- AutoSeeded_RNG rng;
-
- X509_Certificate mycert("mycert.pem");
- PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
-
- X509_Certificate yourcert("yourcert.pem");
- X509_Certificate cacert("cacert.pem");
- X509_Certificate int_ca("int_ca.pem");
-
- X509_Store store;
- store.add_cert(mycert);
- store.add_cert(yourcert);
- store.add_cert(cacert, true);
- store.add_cert(int_ca);
-
- DataSource_Stream message(argv[1]);
-
- CMS_Decoder decoder(message, store, mykey);
-
- while(decoder.layer_type() != CMS_Decoder::DATA)
- {
- CMS_Decoder::Status status = decoder.layer_status();
- CMS_Decoder::Content_Type content = decoder.layer_type();
-
- if(status == CMS_Decoder::FAILURE)
- {
- std::cout << "Failure reading CMS data" << std::endl;
- break;
- }
-
- if(content == CMS_Decoder::DIGESTED)
- {
- std::cout << "Digested data, hash = " << decoder.layer_info()
- << std::endl;
- std::cout << "Hash is "
- << ((status == CMS_Decoder::GOOD) ? "good" : "bad")
- << std::endl;
- }
-
- if(content == CMS_Decoder::SIGNED)
- {
- // how to handle multiple signers? they can all exist within a
- // single level...
-
- std::cout << "Signed by " << decoder.layer_info() << std::endl;
- //std::cout << "Sign time: " << decoder.xxx() << std::endl;
- std::cout << "Signature is ";
- if(status == CMS_Decoder::GOOD)
- std::cout << "valid";
- else if(status == CMS_Decoder::BAD)
- std::cout << "bad";
- else if(status == CMS_Decoder::NO_KEY)
- std::cout << "(cannot check, no known cert)";
- std::cout << std::endl;
- }
- if(content == CMS_Decoder::ENVELOPED ||
- content == CMS_Decoder::COMPRESSED ||
- content == CMS_Decoder::AUTHENTICATED)
- {
- if(content == CMS_Decoder::ENVELOPED)
- std::cout << "Enveloped";
- if(content == CMS_Decoder::COMPRESSED)
- std::cout << "Compressed";
- if(content == CMS_Decoder::AUTHENTICATED)
- std::cout << "MACed";
-
- std::cout << ", algo = " << decoder.layer_info() << std::endl;
-
- if(content == CMS_Decoder::AUTHENTICATED)
- {
- std::cout << "MAC status is ";
- if(status == CMS_Decoder::GOOD)
- std::cout << "valid";
- else if(status == CMS_Decoder::BAD)
- std::cout << "bad";
- else if(status == CMS_Decoder::NO_KEY)
- std::cout << "(cannot check, no key)";
- std::cout << std::endl;
- }
- }
- decoder.next_layer();
- }
-
- if(decoder.layer_type() == CMS_Decoder::DATA)
- std::cout << "Message is \"" << decoder.get_data()
- << '"' << std::endl;
- else
- std::cout << "No data anywhere?" << std::endl;
- }
- catch(std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- }
- return 0;
- }
diff --git a/doc/examples/cms_enc.cpp b/doc/examples/cms_enc.cpp
deleted file mode 100644
index 2cf813987..000000000
--- a/doc/examples/cms_enc.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/botan.h>
-#include <botan/cms_enc.h>
-using namespace Botan;
-
-#include <iostream>
-#include <fstream>
-#include <memory>
-
-int main()
- {
- Botan::LibraryInitializer init;
-
- try {
-
- X509_Certificate mycert("mycert.pem");
- X509_Certificate mycert2("mycert2.pem");
- X509_Certificate yourcert("yourcert.pem");
- X509_Certificate cacert("cacert.pem");
- X509_Certificate int_ca("int_ca.pem");
-
- AutoSeeded_RNG rng;
-
- X509_Store store;
- store.add_cert(mycert);
- store.add_cert(mycert2);
- store.add_cert(yourcert);
- store.add_cert(int_ca);
- store.add_cert(cacert, true);
-
- const std::string msg = "prioncorp: we don't toy\n";
-
- CMS_Encoder encoder(msg);
-
- encoder.compress("Zlib");
- encoder.digest();
- encoder.encrypt(rng, mycert);
-
- /*
- PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
- encoder.sign(store, *mykey);
- */
-
- SecureVector<byte> raw = encoder.get_contents();
- std::ofstream out("out.der");
-
- out.write((const char*)raw.begin(), raw.size());
- }
- catch(std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- }
- return 0;
- }
diff --git a/doc/examples/credentials.h b/doc/examples/credentials.h
new file mode 100644
index 000000000..2734b1649
--- /dev/null
+++ b/doc/examples/credentials.h
@@ -0,0 +1,284 @@
+
+#ifndef EXAMPLE_CREDENTIALS_MANAGER_H__
+#define EXAMPLE_CREDENTIALS_MANAGER_H__
+
+#include <botan/credentials_manager.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/srp6.h>
+#include <botan/srp6_files.h>
+#include <botan/ecdsa.h>
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+bool value_exists(const std::vector<std::string>& vec,
+ const std::string& val)
+ {
+ for(size_t i = 0; i != vec.size(); ++i)
+ if(vec[i] == val)
+ return true;
+ return false;
+ }
+
+class Credentials_Manager_Simple : public Botan::Credentials_Manager
+ {
+ public:
+ Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {}
+
+ std::string srp_identifier(const std::string& type,
+ const std::string& hostname)
+ {
+ if(type == "tls-client" && hostname == "srp-host")
+ return "user";
+ return "";
+ }
+
+ bool attempt_srp(const std::string& type,
+ const std::string& hostname)
+ {
+ if(hostname == "srp-host")
+ return true;
+ return false;
+ }
+
+ std::vector<Botan::X509_Certificate>
+ trusted_certificate_authorities(const std::string& type,
+ const std::string& hostname)
+ {
+
+ std::vector<Botan::X509_Certificate> certs;
+
+ if(type == "tls-server" && hostname == "localhost")
+ {
+ Botan::X509_Certificate testca("testCA.crt");
+ certs.push_back(testca);
+ }
+
+ if(type == "tls-client" && hostname == "twitter.com")
+ {
+ Botan::X509_Certificate verisign("/usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt");
+ certs.push_back(verisign);
+ }
+
+ return certs;
+ }
+
+ void verify_certificate_chain(
+ const std::string& type,
+ const std::string& purported_hostname,
+ const std::vector<Botan::X509_Certificate>& cert_chain)
+ {
+ try
+ {
+ Botan::Credentials_Manager::verify_certificate_chain(type,
+ purported_hostname,
+ cert_chain);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Certificate verification failed - " << e.what() << " - but will ignore\n";
+ }
+ }
+
+ std::string srp_password(const std::string& type,
+ const std::string& hostname,
+ const std::string& identifier)
+ {
+ if(type == "tls-client" && hostname == "localhost" && identifier == "user")
+ return "password";
+
+ return "";
+ }
+
+ bool srp_verifier(const std::string& type,
+ const std::string& context,
+ const std::string& identifier,
+ std::string& group_id,
+ Botan::BigInt& verifier,
+ std::vector<Botan::byte>& salt,
+ bool generate_fake_on_unknown)
+ {
+
+ std::string pass = srp_password("tls-client", context, identifier);
+ if(pass == "")
+ {
+ if(!generate_fake_on_unknown)
+ return false;
+
+ pass.resize(16);
+ Botan::global_state().global_rng().randomize((Botan::byte*)&pass[0], pass.size());
+ }
+
+ group_id = "modp/srp/2048";
+
+ salt.resize(16);
+ Botan::global_state().global_rng().randomize(&salt[0], salt.size());
+
+ verifier = Botan::generate_srp6_verifier(identifier,
+ pass,
+ salt,
+ group_id,
+ "SHA-1");
+
+ return true;
+ }
+
+ std::string psk_identity_hint(const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+ std::string psk_identity(const std::string&, const std::string&,
+ const std::string& identity_hint)
+ {
+ //return "lloyd";
+ return "Client_identity";
+ }
+
+ Botan::SymmetricKey psk(const std::string& type, const std::string& context,
+ const std::string& identity)
+ {
+ if(type == "tls-server" && context == "session-ticket")
+ {
+ if(session_ticket_key.length() == 0)
+ session_ticket_key = Botan::SymmetricKey(rng, 32);
+ return session_ticket_key;
+ }
+
+ if(identity == "Client_identity")
+ return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527");
+ if(identity == "lloyd")
+ return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630");
+
+ throw Botan::Internal_Error("No PSK set for " + identity);
+ }
+
+ std::pair<Botan::X509_Certificate,Botan::Private_Key*>
+ load_or_make_cert(const std::string& hostname,
+ const std::string& key_type,
+ Botan::RandomNumberGenerator& rng)
+ {
+ using namespace Botan;
+
+ const std::string key_fsname_prefix = hostname + "." + key_type + ".";
+ const std::string key_file_name = key_fsname_prefix + "key";
+ const std::string cert_file_name = key_fsname_prefix + "crt";
+
+ try
+ {
+ X509_Certificate cert(cert_file_name);
+ Private_Key* key = PKCS8::load_key(key_file_name, rng);
+
+ //std::cout << "Loaded existing key/cert from " << cert_file_name << " and " << key_file_name << "\n";
+
+ return std::make_pair(cert, key);
+ }
+ catch(...) {}
+
+ // Failed. Instead, make a new one
+
+ std::cout << "Creating new certificate for identifier '" << hostname << "'\n";
+
+ X509_Cert_Options opts;
+
+ opts.common_name = hostname;
+ opts.country = "US";
+ opts.email = "root@" + hostname;
+ opts.dns = hostname;
+
+ std::auto_ptr<Private_Key> key;
+ if(key_type == "rsa")
+ key.reset(new RSA_PrivateKey(rng, 1024));
+ else if(key_type == "dsa")
+ key.reset(new DSA_PrivateKey(rng, DL_Group("dsa/jce/1024")));
+ else if(key_type == "ecdsa")
+ key.reset(new ECDSA_PrivateKey(rng, EC_Group("secp256r1")));
+ else
+ throw std::runtime_error("Don't know what to do about key type '" + key_type + "'");
+
+ X509_Certificate cert =
+ X509::create_self_signed_cert(opts, *key, "SHA-1", rng);
+
+ // Now save both
+
+ std::cout << "Saving new " << key_type << " key to " << key_file_name << "\n";
+ std::ofstream key_file(key_file_name.c_str());
+ key_file << PKCS8::PEM_encode(*key, rng, "");
+ key_file.close();
+
+ std::cout << "Saving new " << key_type << " cert to " << key_file_name << "\n";
+ std::ofstream cert_file(cert_file_name.c_str());
+ cert_file << cert.PEM_encode() << "\n";
+ cert_file.close();
+
+ return std::make_pair(cert, key.release());
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context)
+ {
+ using namespace Botan;
+
+ std::vector<X509_Certificate> certs;
+
+ try
+ {
+ if(type == "tls-server")
+ {
+ const std::string hostname = (context == "" ? "localhost" : context);
+
+ if(hostname == "nosuchname")
+ return std::vector<Botan::X509_Certificate>();
+
+ std::string key_name = "";
+
+ if(value_exists(cert_key_types, "RSA"))
+ key_name = "rsa";
+ else if(value_exists(cert_key_types, "DSA"))
+ key_name = "dsa";
+ else if(value_exists(cert_key_types, "ECDSA"))
+ key_name = "ecdsa";
+
+ std::pair<X509_Certificate, Private_Key*> cert_and_key =
+ load_or_make_cert(hostname, key_name, rng);
+
+ certs_and_keys[cert_and_key.first] = cert_and_key.second;
+ certs.push_back(cert_and_key.first);
+ }
+ else if(type == "tls-client")
+ {
+ X509_Certificate cert("user-rsa.crt");
+ Private_Key* key = PKCS8::load_key("user-rsa.key", rng);
+
+ certs_and_keys[cert] = key;
+ certs.push_back(cert);
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+
+ return certs;
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context)
+ {
+ return certs_and_keys[cert];
+ }
+
+ private:
+ Botan::RandomNumberGenerator& rng;
+
+ Botan::SymmetricKey session_ticket_key;
+ std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
+ };
+
+#endif
diff --git a/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp
index ea510c5e9..42c4071c7 100644
--- a/doc/examples/decrypt.cpp
+++ b/doc/examples/decrypt.cpp
@@ -27,7 +27,7 @@ stderr so there is no confusion.
using namespace Botan;
-SecureVector<byte> b64_decode(const std::string&);
+secure_vector<byte> b64_decode(const std::string&);
int main(int argc, char* argv[])
{
@@ -111,7 +111,7 @@ int main(int argc, char* argv[])
const u32bit PBKDF2_ITERATIONS = 8192;
- SecureVector<byte> salt = b64_decode(salt_str);
+ secure_vector<byte> salt = b64_decode(salt_str);
SymmetricKey bc_key = pbkdf->derive_key(key_len, "BLK" + passphrase,
&salt[0], salt.size(),
@@ -165,7 +165,7 @@ int main(int argc, char* argv[])
return 0;
}
-SecureVector<byte> b64_decode(const std::string& in)
+secure_vector<byte> b64_decode(const std::string& in)
{
Pipe pipe(new Base64_Decoder);
pipe.process_msg(in);
diff --git a/doc/examples/dh.cpp b/doc/examples/dh.cpp
index 8d163303a..d62d49f65 100644
--- a/doc/examples/dh.cpp
+++ b/doc/examples/dh.cpp
@@ -24,12 +24,12 @@ int main()
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();
+ std::vector<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();
+ std::vector<byte> public_b = private_b.public_value();
// Now Alice performs the key agreement operation
PK_Key_Agreement ka_alice(private_a, "KDF2(SHA-256)");
diff --git a/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp
index 9cb85740e..e6910a4e1 100644
--- a/doc/examples/dsa_ver.cpp
+++ b/doc/examples/dsa_ver.cpp
@@ -12,7 +12,7 @@ using namespace Botan;
namespace {
-SecureVector<byte> b64_decode(const std::string& in)
+secure_vector<byte> b64_decode(const std::string& in)
{
Pipe pipe(new Base64_Decoder);
pipe.process_msg(in);
@@ -60,7 +60,7 @@ int main(int argc, char* argv[])
return 1;
}
- SecureVector<byte> sig = b64_decode(sigstr);
+ secure_vector<byte> sig = b64_decode(sigstr);
PK_Verifier ver(*dsakey, "EMSA1(SHA-1)");
diff --git a/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp
index 1607107eb..b0a66a888 100644
--- a/doc/examples/ecdsa.cpp
+++ b/doc/examples/ecdsa.cpp
@@ -40,7 +40,7 @@ int main()
signer.update((const byte*)message, strlen(message));
- SecureVector<byte> sig = signer.signature(rng);
+ std::vector<byte> sig = signer.signature(rng);
std::cout << sig.size() << "\n";
diff --git a/doc/examples/encrypt.cpp b/doc/examples/encrypt.cpp
index 28017d875..158806936 100644
--- a/doc/examples/encrypt.cpp
+++ b/doc/examples/encrypt.cpp
@@ -33,7 +33,7 @@ you're encrypting is 1 Gb... you better have a lot of RAM.
using namespace Botan;
-std::string b64_encode(const SecureVector<byte>&);
+std::string b64_encode(const secure_vector<byte>&);
int main(int argc, char* argv[])
{
@@ -128,7 +128,7 @@ int main(int argc, char* argv[])
std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)"));
- SecureVector<byte> salt(8);
+ secure_vector<byte> salt(8);
rng.randomize(&salt[0], salt.size());
const u32bit PBKDF2_ITERATIONS = 8192;
@@ -185,7 +185,7 @@ int main(int argc, char* argv[])
return 0;
}
-std::string b64_encode(const SecureVector<byte>& in)
+std::string b64_encode(const secure_vector<byte>& in)
{
Pipe pipe(new Base64_Encoder);
pipe.process_msg(in);
diff --git a/doc/examples/encrypt2.cpp b/doc/examples/encrypt2.cpp
index 41f4fb478..c6c735af9 100644
--- a/doc/examples/encrypt2.cpp
+++ b/doc/examples/encrypt2.cpp
@@ -28,10 +28,10 @@ int main()
const u32bit PBKDF2_ITERATIONS = 8192;
- SecureVector<byte> salt(8);
+ secure_vector<byte> salt(8);
rng.randomize(&salt[0], salt.size());
- SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase,
+ secure_vector<byte> master_key = pbkdf2.derive_key(48, passphrase,
&salt[0], salt.size(),
PBKDF2_ITERATIONS).bits_of();
@@ -55,12 +55,12 @@ int main()
)
);
- outfile.write((const char*)salt.begin(), salt.size());
+ outfile.write((const char*)&salt[0], salt.size());
pipe.start_msg();
infile >> pipe;
pipe.end_msg();
- SecureVector<byte> hmac = pipe.read_all(1);
- outfile.write((const char*)hmac.begin(), hmac.size());
+ secure_vector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)&hmac[0], hmac.size());
}
diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp
index 029a761e7..8f5eaca9f 100644
--- a/doc/examples/fpe.cpp
+++ b/doc/examples/fpe.cpp
@@ -55,11 +55,11 @@ u64bit cc_derank(u64bit cc_number)
/*
* Use the SHA-1 hash of the account name or ID as a tweak
*/
-SecureVector<byte> sha1(const std::string& acct_name)
+std::vector<byte> sha1(const std::string& acct_name)
{
SHA_160 hash;
hash.update(acct_name);
- return hash.final();
+ return unlock(hash.final());
}
u64bit encrypt_cc_number(u64bit cc_number,
@@ -123,7 +123,7 @@ int main(int argc, char* argv[])
* In practice something like PBKDF2 with a salt and high iteration
* count would be a good idea.
*/
- SymmetricKey key = sha1(passwd);
+ SymmetricKey key(sha1(passwd));
u64bit enc_cc = encrypt_cc_number(cc_number, key, acct_name);
diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp
index f8c9fe124..14ae5a0a9 100644
--- a/doc/examples/gen_certs.cpp
+++ b/doc/examples/gen_certs.cpp
@@ -11,9 +11,9 @@
#include <botan/botan.h>
#include <botan/rsa.h>
-#include <botan/time.h>
#include <botan/x509self.h>
#include <botan/x509_ca.h>
+#include <chrono>
using namespace Botan;
@@ -81,14 +81,14 @@ void save_pair(const std::string& name,
}
+typedef std::chrono::duration<int, std::ratio<31556926>> years;
+
int main()
{
- const u32bit seconds_in_a_year = 31556926;
-
- const u32bit current_time = system_time();
+ auto current_time = std::chrono::system_clock::now();
X509_Time now = X509_Time(current_time);
- X509_Time later = X509_Time(current_time + 4*seconds_in_a_year);
+ X509_Time later = X509_Time(current_time + years(4));
LibraryInitializer init;
diff --git a/doc/examples/hash_quickly.cpp b/doc/examples/hash_quickly.cpp
index a18ab4fa6..87937efff 100644
--- a/doc/examples/hash_quickly.cpp
+++ b/doc/examples/hash_quickly.cpp
@@ -29,7 +29,7 @@ namespace {
void set_fastest_implementation(const std::string& algo,
Botan::RandomNumberGenerator& rng,
- double ms = 30)
+ std::chrono::milliseconds ms = std::chrono::milliseconds(30))
{
Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
diff --git a/doc/examples/keywrap.cpp b/doc/examples/keywrap.cpp
index 730bcb6c9..93cdbfb84 100644
--- a/doc/examples/keywrap.cpp
+++ b/doc/examples/keywrap.cpp
@@ -28,11 +28,11 @@ int main()
Algorithm_Factory& af = global_state().algorithm_factory();
- SecureVector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af);
+ secure_vector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af);
std::cout << "Encrypted: " << hex_encode(enc) << "\n";
- SecureVector<byte> dec = rfc3394_keyunwrap(enc, kek, af);
+ secure_vector<byte> dec = rfc3394_keyunwrap(enc, kek, af);
std::cout << "Decrypted: " << hex_encode(dec) << "\n";
}
diff --git a/doc/examples/new_engine.cpp b/doc/examples/new_engine.cpp
index 42e5dbe33..7e51df2e2 100644
--- a/doc/examples/new_engine.cpp
+++ b/doc/examples/new_engine.cpp
@@ -43,7 +43,7 @@ class XOR_Cipher : public StreamCipher
copy_mem(&mask[0], key, length);
}
- SecureVector<byte> mask;
+ secure_vector<byte> mask;
u32bit mask_pos;
};
diff --git a/doc/examples/pqg_gen.cpp b/doc/examples/pqg_gen.cpp
index c033dac3b..b24c30844 100644
--- a/doc/examples/pqg_gen.cpp
+++ b/doc/examples/pqg_gen.cpp
@@ -13,7 +13,7 @@
#include <botan/botan.h>
#include <botan/auto_rng.h>
-#include <botan/dsa.h>
+#include <botan/hex.h>
#include <botan/numthry.h>
#include <botan/dl_group.h>
using namespace Botan;
@@ -94,9 +94,7 @@ bool check(RandomNumberGenerator& rng,
//u32bit c = to_u32bit(inputs["c"]);
- Pipe pipe(new Hex_Decoder);
- pipe.process_msg(inputs["Seed"]);
- SecureVector<byte> seed = pipe.read_all();
+ std::vector<byte> seed = unlock(hex_decode(inputs["Seed"]));
BigInt our_p, our_q;
diff --git a/doc/examples/read_ssh.cpp b/doc/examples/read_ssh.cpp
index f6299a29d..0392786a5 100644
--- a/doc/examples/read_ssh.cpp
+++ b/doc/examples/read_ssh.cpp
@@ -42,7 +42,7 @@ BigInt read_bigint(Pipe& pipe)
{
u32bit len = read_u32bit(pipe);
- SecureVector<byte> buf(len);
+ secure_vector<byte> buf(len);
pipe.read(&buf[0], len);
return BigInt::decode(buf);
}
diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp
index c0d24fd80..385ac57f3 100644
--- a/doc/examples/rng_test.cpp
+++ b/doc/examples/rng_test.cpp
@@ -68,11 +68,11 @@ void x931_tests(std::vector<std::pair<std::string, std::string> > vecs,
ANSI_X931_RNG prng(get_block_cipher(cipher),
new Fixed_Output_RNG);
- SecureVector<byte> x = hex_decode(input);
- prng.add_entropy(x.begin(), x.size());
+ secure_vector<byte> x = hex_decode(input);
+ prng.add_entropy(&x[0], x.size());
- SecureVector<byte> output(result.size() / 2);
- prng.randomize(output, output.size());
+ secure_vector<byte> output(result.size() / 2);
+ prng.randomize(&output[0], output.size());
if(hex_decode(result) != output)
std::cout << "FAIL";
diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp
index 685850945..b512025b6 100644
--- a/doc/examples/row_encryptor.cpp
+++ b/doc/examples/row_encryptor.cpp
@@ -26,22 +26,22 @@ class Row_Encryptor
RandomNumberGenerator& rng);
Row_Encryptor(const std::string& passphrase,
- const MemoryRegion<byte>& salt);
+ const std::vector<byte>& salt);
std::string encrypt(const std::string& input,
- const MemoryRegion<byte>& salt);
+ const std::vector<byte>& salt);
std::string decrypt(const std::string& input,
- const MemoryRegion<byte>& salt);
+ const std::vector<byte>& salt);
- SecureVector<byte> get_pbkdf_salt() const { return pbkdf_salt; }
+ std::vector<byte> get_pbkdf_salt() const { return pbkdf_salt; }
private:
void init(const std::string& passphrase);
Row_Encryptor(const Row_Encryptor&) {}
Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); }
- SecureVector<byte> pbkdf_salt;
+ std::vector<byte> pbkdf_salt;
Pipe enc_pipe, dec_pipe;
EAX_Encryption* eax_enc; // owned by enc_pipe
EAX_Decryption* eax_dec; // owned by dec_pipe;
@@ -56,7 +56,7 @@ Row_Encryptor::Row_Encryptor(const std::string& passphrase,
}
Row_Encryptor::Row_Encryptor(const std::string& passphrase,
- const MemoryRegion<byte>& salt)
+ const std::vector<byte>& salt)
{
pbkdf_salt = salt;
init(passphrase);
@@ -66,7 +66,7 @@ void Row_Encryptor::init(const std::string& passphrase)
{
std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-160)"));
- SecureVector<byte> key = pbkdf->derive_key(32, passphrase,
+ secure_vector<byte> key = pbkdf->derive_key(32, passphrase,
&pbkdf_salt[0], pbkdf_salt.size(),
10000).bits_of();
@@ -89,7 +89,7 @@ void Row_Encryptor::init(const std::string& passphrase)
}
std::string Row_Encryptor::encrypt(const std::string& input,
- const MemoryRegion<byte>& salt)
+ const std::vector<byte>& salt)
{
eax_enc->set_iv(salt);
enc_pipe.process_msg(input);
@@ -97,7 +97,7 @@ std::string Row_Encryptor::encrypt(const std::string& input,
}
std::string Row_Encryptor::decrypt(const std::string& input,
- const MemoryRegion<byte>& salt)
+ const std::vector<byte>& salt)
{
eax_dec->set_iv(salt);
dec_pipe.process_msg(input);
@@ -133,7 +133,7 @@ int main()
}
std::vector<std::string> encrypted_values;
- MemoryVector<byte> salt(4); // keep out of loop to avoid excessive dynamic allocation
+ std::vector<byte> salt(4);
for(u32bit i = 0; i != original_inputs.size(); ++i)
{
diff --git a/doc/examples/rsa_dec.cpp b/doc/examples/rsa_dec.cpp
index 81592328c..98768cda7 100644
--- a/doc/examples/rsa_dec.cpp
+++ b/doc/examples/rsa_dec.cpp
@@ -20,7 +20,7 @@ same key format as that generated by rsa_kgen.
#include <botan/rsa.h>
using namespace Botan;
-SecureVector<byte> b64_decode(const std::string&);
+secure_vector<byte> b64_decode(const std::string&);
SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
const std::string SUFFIX = ".enc";
@@ -41,7 +41,7 @@ int main(int argc, char* argv[])
AutoSeeded_RNG rng;
std::auto_ptr<PKCS8_PrivateKey> key(
- PKCS8::load_key(argv[1], rng, argv[3]));
+ PKCS8::load_key(std::string(argv[1]), rng, std::string(argv[3])));
RSA_PrivateKey* rsakey = dynamic_cast<RSA_PrivateKey*>(key.get());
if(!rsakey)
@@ -73,11 +73,11 @@ int main(int argc, char* argv[])
std::string mac_str;
std::getline(message, mac_str);
- SecureVector<byte> enc_masterkey = b64_decode(enc_masterkey_str);
+ secure_vector<byte> enc_masterkey = b64_decode(enc_masterkey_str);
PK_Decryptor_EME decryptor(*rsakey, "EME1(SHA-1)");
- SecureVector<byte> masterkey = decryptor.decrypt(enc_masterkey);
+ secure_vector<byte> masterkey = decryptor.decrypt(enc_masterkey);
SymmetricKey cast_key = derive_key("CAST", masterkey, 16);
InitializationVector iv = derive_key("IV", masterkey, 8);
@@ -113,7 +113,7 @@ int main(int argc, char* argv[])
return 0;
}
-SecureVector<byte> b64_decode(const std::string& in)
+secure_vector<byte> b64_decode(const std::string& in)
{
Pipe pipe(new Base64_Decoder);
pipe.process_msg(in);
diff --git a/doc/examples/rsa_enc.cpp b/doc/examples/rsa_enc.cpp
index ac609c4b3..b8e5d874b 100644
--- a/doc/examples/rsa_enc.cpp
+++ b/doc/examples/rsa_enc.cpp
@@ -34,9 +34,10 @@
#include <botan/botan.h>
#include <botan/pubkey.h>
#include <botan/rsa.h>
+#include <botan/base64.h>
+
using namespace Botan;
-std::string b64_encode(const SecureVector<byte>&);
SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
int main(int argc, char* argv[])
@@ -98,10 +99,10 @@ int main(int argc, char* argv[])
SymmetricKey mac_key = derive_key("MAC", masterkey, 16);
SymmetricKey iv = derive_key("IV", masterkey, 8);
- SecureVector<byte> encrypted_key =
+ std::vector<byte> encrypted_key =
encryptor.encrypt(masterkey.bits_of(), rng);
- ciphertext << b64_encode(encrypted_key) << std::endl;
+ ciphertext << base64_encode(encrypted_key) << std::endl;
Pipe pipe(new Fork(
new Chain(
@@ -135,13 +136,6 @@ int main(int argc, char* argv[])
return 0;
}
-std::string b64_encode(const SecureVector<byte>& in)
- {
- Pipe pipe(new Base64_Encoder);
- pipe.process_msg(in);
- return pipe.read_all_as_string();
- }
-
SymmetricKey derive_key(const std::string& param,
const SymmetricKey& masterkey,
u32bit outputlength)
diff --git a/doc/examples/rsa_manykey.cpp b/doc/examples/rsa_manykey.cpp
index e6a511753..c282e7882 100644
--- a/doc/examples/rsa_manykey.cpp
+++ b/doc/examples/rsa_manykey.cpp
@@ -31,7 +31,7 @@ int main()
RSA_PrivateKey key(rng, j);
- std::ofstream priv(("rsa/" + to_string(j) + ".pem").c_str());
+ std::ofstream priv(("rsa/" + std::to_string(j) + ".pem").c_str());
priv << PKCS8::PEM_encode(key);
priv.close();
diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp
index 64b778b71..7cb159db9 100644
--- a/doc/examples/self_sig.cpp
+++ b/doc/examples/self_sig.cpp
@@ -36,6 +36,9 @@ int main(int argc, char* argv[])
AutoSeeded_RNG rng;
RSA_PrivateKey key(rng, 2048);
+ //DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
+
+ //DSA_PrivateKey key(rng, group);
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
index f7ce98fea..9e16ab36a 100644
--- a/doc/examples/socket.h
+++ b/doc/examples/socket.h
@@ -48,6 +48,7 @@
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
+ #include <fcntl.h>
typedef int socket_t;
const socket_t invalid_socket = -1;
@@ -66,7 +67,7 @@
class Socket
{
public:
- size_t read(unsigned char[], size_t);
+ size_t read(unsigned char[], size_t, bool dont_block = false);
void write(const unsigned char[], size_t);
std::string peer_id() const { return peer; }
@@ -158,23 +159,28 @@ Socket::Socket(const std::string& host, unsigned short port) : peer(host)
throw std::runtime_error("Socket: connect failed");
}
+ //fcntl(fd, F_SETFL, O_NONBLOCK);
+
sockfd = fd;
}
/**
* Read from a Unix socket
*/
-size_t Socket::read(unsigned char buf[], size_t length)
+size_t Socket::read(unsigned char buf[], size_t length, bool partial)
{
if(sockfd == invalid_socket)
throw std::runtime_error("Socket::read: Socket not connected");
size_t got = 0;
+ int flags = MSG_NOSIGNAL;
+
while(length)
{
- ssize_t this_time = ::recv(sockfd, (char*)buf + got,
- length, MSG_NOSIGNAL);
+ ssize_t this_time = ::recv(sockfd, (char*)buf + got, length, flags);
+
+ const bool full_ret = (this_time == (ssize_t)length);
if(this_time == 0)
break;
@@ -183,13 +189,19 @@ size_t Socket::read(unsigned char buf[], size_t length)
{
if(socket_error_code == EINTR)
this_time = 0;
+ else if(socket_error_code == EAGAIN)
+ break;
else
throw std::runtime_error("Socket::read: Socket read failed");
}
got += this_time;
length -= this_time;
+
+ if(partial && !full_ret)
+ break;
}
+
return got;
}
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index cedfe1ca8..deb0ff460 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -1,91 +1,242 @@
#include <botan/botan.h>
#include <botan/tls_client.h>
-#include "socket.h"
-
-using namespace Botan;
-
+#include <botan/pkcs8.h>
+#include <botan/hex.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory>
-class Client_TLS_Policy : public TLS_Policy
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if defined(BOTAN_HAS_TLS_SQLITE_SESSION_MANAGER)
+ #include <botan/tls_sqlite_sess_mgr.h>
+#endif
+
+#include "credentials.h"
+
+using namespace Botan;
+
+using namespace std::placeholders;
+
+int connect_to_host(const std::string& host, u16bit port)
{
- public:
- bool check_cert(const std::vector<X509_Certificate>& certs) const
- {
- for(size_t i = 0; i != certs.size(); ++i)
- {
- std::cout << certs[i].to_string();
- }
+ hostent* host_addr = ::gethostbyname(host.c_str());
+
+ if(host_addr == 0)
+ throw std::runtime_error("gethostbyname failed for " + host);
+
+ if(host_addr->h_addrtype != AF_INET) // FIXME
+ throw std::runtime_error(host + " has IPv6 address");
+
+ int fd = ::socket(PF_INET, SOCK_STREAM, 0);
+ if(fd == -1)
+ throw std::runtime_error("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 std::runtime_error("connect failed");
+ }
+
+ return fd;
+ }
+
+bool handshake_complete(const TLS::Session& session)
+ {
+ std::cout << "Handshake complete!\n";
+ std::cout << "Protocol version " << session.version().to_string() << "\n";
+ std::cout << "Ciphersuite " << std::hex << session.ciphersuite().to_string() << "\n";
+ std::cout << "Session ID " << hex_encode(session.session_id()) << "\n";
+ std::cout << "Session ticket " << hex_encode(session.session_ticket()) << "\n";
- std::cout << "Warning: not checking cert signatures\n";
+ return true;
+ }
+
+void socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ size_t offset = 0;
- return true;
+ while(length)
+ {
+ ssize_t sent = ::send(sockfd, (const char*)buf + offset,
+ length, MSG_NOSIGNAL);
+
+ if(sent == -1)
+ {
+ if(errno == EINTR)
+ sent = 0;
+ else
+ throw std::runtime_error("Socket::write: Socket write failed");
}
- };
-int main(int argc, char* argv[])
+ offset += sent;
+ length -= sent;
+ }
+ }
+
+bool got_alert = false;
+
+void process_data(const byte buf[], size_t buf_size, TLS::Alert alert)
{
- if(argc != 2 && argc != 3)
+ if(alert.is_valid())
{
- printf("Usage: %s host [port]\n", argv[0]);
- return 1;
+ std::cout << "Alert: " << alert.type_string() << "\n";
+ got_alert = true;
}
- try
+ for(size_t i = 0; i != buf_size; ++i)
{
- LibraryInitializer botan_init;
+ std::cout << buf[i];
+ }
+ }
- std::string host = argv[1];
- u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;
+std::string protocol_chooser(const std::vector<std::string>& protocols)
+ {
+ for(size_t i = 0; i != protocols.size(); ++i)
+ std::cout << "Protocol " << i << " = " << protocols[i] << "\n";
+ return "http/1.1";
+ }
- printf("Connecting to %s:%d...\n", host.c_str(), port);
+void doit(RandomNumberGenerator& rng,
+ TLS::Policy& policy,
+ TLS::Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const std::string& host,
+ u16bit port)
+ {
+ int sockfd = connect_to_host(host, port);
- SocketInitializer socket_init;
+ TLS::Client client(std::bind(socket_write, sockfd, _1, _2),
+ process_data,
+ handshake_complete,
+ session_manager,
+ creds,
+ policy,
+ rng,
+ host);
- Socket sock(argv[1], port);
+ fd_set readfds;
- AutoSeeded_RNG rng;
+ while(true)
+ {
+ FD_ZERO(&readfds);
+ FD_SET(sockfd, &readfds);
+ FD_SET(STDIN_FILENO, &readfds);
- Client_TLS_Policy policy;
+ ::select(sockfd + 1, &readfds, NULL, NULL, NULL);
- 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);
+ if(client.is_closed())
+ break;
- printf("Handshake extablished...\n");
+ if(FD_ISSET(sockfd, &readfds))
+ {
+ byte buf[64] = { 0 };
-#if 0
- std::string http_command = "GET / HTTP/1.1\r\n"
- "Server: " + host + ':' + to_string(port) + "\r\n\r\n";
-#else
- std::string http_command = "GET / HTTP/1.0\r\n\r\n";
-#endif
+ size_t to_read = rand() % sizeof(buf);
+ if(to_read == 0)
+ to_read = 1;
- tls.write((const Botan::byte*)http_command.c_str(),
- http_command.length());
+ ssize_t got = read(sockfd, buf, to_read);
- size_t total_got = 0;
+ if(got == 0)
+ {
+ std::cout << "EOF on socket\n";
+ break;
+ }
+ else if(got == -1)
+ {
+ std::cout << "Socket error: " << errno << " " << strerror(errno) << "\n";
+ continue;
+ }
- while(true)
+ client.received_data(buf, got);
+ //std::cout << "Socket - got " << got << " bytes, need " << needed << "\n";
+ }
+ else if(FD_ISSET(STDIN_FILENO, &readfds))
{
- if(tls.is_closed())
- break;
+ byte buf[1024] = { 0 };
+ ssize_t got = read(STDIN_FILENO, buf, sizeof(buf));
- Botan::byte buf[128+1] = { 0 };
- size_t got = tls.read(buf, sizeof(buf)-1);
- printf("%s", buf);
- fflush(0);
+ if(got == 0)
+ {
+ std::cout << "EOF on stdin\n";
+ client.close();
+ break;
+ }
+ else if(got == -1)
+ {
+ std::cout << "Stdin error: " << errno << " " << strerror(errno) << "\n";
+ continue;
+ }
- total_got += got;
+ if(got == 2 && (buf[0] == 'R' || buf[0] == 'r') && buf[1] == '\n')
+ {
+ std::cout << "Client initiated renegotiation\n";
+ client.renegotiate((buf[0] == 'R'));
+ }
+
+ if(buf[0] == 'H')
+ client.heartbeat(&buf[1], got-1);
+ else
+ client.send(buf, got);
}
+ }
+
+ ::close(sockfd);
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cout << "Usage " << argv[0] << " host [port]\n";
+ return 1;
+ }
+
+ try
+ {
+ LibraryInitializer botan_init;
+ AutoSeeded_RNG rng;
+ TLS::Policy policy;
+
+#if defined(BOTAN_HAS_TLS_SQLITE_SESSION_MANAGER)
+ TLS::Session_Manager_SQLite session_manager("my secret passphrase", rng,
+ "sessions.db");
+#else
+ TLS::Session_Manager_In_Memory session_manager;
+#endif
+
+ Credentials_Manager_Simple creds(rng);
+
+ std::string host = argv[1];
+ u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;
+
+ //while(true)
+ doit(rng, policy, session_manager, creds, host, port);
- printf("\nRetrieved %d bytes total\n", total_got);
}
catch(std::exception& e)
{
- printf("%s\n", e.what());
+ std::cout << "Exception: " << e.what() << "\n";
return 1;
}
return 0;
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index 153b26d04..727f4c333 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -1,33 +1,140 @@
#include <botan/botan.h>
#include <botan/tls_server.h>
+#include <botan/hex.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
#include <botan/x509self.h>
+#include <botan/secqueue.h>
#include "socket.h"
+#include "credentials.h"
using namespace Botan;
+using namespace std::placeholders;
+
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory>
-class Server_TLS_Policy : public TLS_Policy
+class Blocking_TLS_Server
{
public:
- bool check_cert(const std::vector<X509_Certificate>& certs) const
+ Blocking_TLS_Server(std::function<void (const byte[], size_t)> output_fn,
+ std::function<size_t (byte[], size_t)> input_fn,
+ std::vector<std::string>& protocols,
+ TLS::Session_Manager& sessions,
+ Credentials_Manager& creds,
+ TLS::Policy& policy,
+ RandomNumberGenerator& rng) :
+ input_fn(input_fn),
+ server(
+ output_fn,
+ std::bind(&Blocking_TLS_Server::reader_fn, std::ref(*this), _1, _2, _3),
+ std::bind(&Blocking_TLS_Server::handshake_complete, std::ref(*this), _1),
+ sessions,
+ creds,
+ policy,
+ rng,
+ protocols),
+ exit(false)
+ {
+ read_loop();
+ }
+
+ bool handshake_complete(const TLS::Session& session)
+ {
+ std::cout << "Handshake complete: "
+ << session.version().to_string() << " "
+ << session.ciphersuite().to_string() << " "
+ << "SessionID: " << hex_encode(session.session_id()) << "\n";
+
+ if(session.srp_identifier() != "")
+ std::cout << "SRP identifier: " << session.srp_identifier() << "\n";
+
+ if(server.next_protocol() != "")
+ std::cout << "Next protocol: " << server.next_protocol() << "\n";
+
+ /*
+ std::vector<X509_Certificate> peer_certs = session.peer_certs();
+ if(peer_certs.size())
+ std::cout << peer_certs[0].to_string();
+ */
+
+ return true;
+ }
+
+ size_t read(byte buf[], size_t buf_len)
{
- for(size_t i = 0; i != certs.size(); ++i)
+ size_t got = read_queue.read(buf, buf_len);
+
+ while(!exit && !got)
{
- std::cout << certs[i].to_string();
+ read_loop(TLS::TLS_HEADER_SIZE);
+ got = read_queue.read(buf, buf_len);
}
- std::cout << "Warning: not checking cert signatures\n";
+ return got;
+ }
- return true;
+ void write(const byte buf[], size_t buf_len)
+ {
+ server.send(buf, buf_len);
+ }
+
+ void close() { server.close(); }
+
+ bool is_active() const { return server.is_active(); }
+
+ TLS::Server& underlying() { return server; }
+ private:
+ void read_loop(size_t init_desired = 0)
+ {
+ size_t desired = init_desired;
+
+ byte buf[4096];
+ while(!exit && (!server.is_active() || desired))
+ {
+ const size_t asking = std::max(sizeof(buf), std::min(desired, static_cast<size_t>(1)));
+
+ const size_t socket_got = input_fn(&buf[0], asking);
+
+ if(socket_got == 0) // eof?
+ {
+ close();
+ printf("got eof on socket\n");
+ exit = true;
+ }
+
+ desired = server.received_data(&buf[0], socket_got);
+ }
+ }
+
+ void reader_fn(const byte buf[], size_t buf_len, TLS::Alert alert)
+ {
+ if(alert.is_valid())
+ {
+ printf("Alert %s\n", alert.type_string().c_str());
+ //exit = true;
+ }
+
+ printf("Got %d bytes: ", (int)buf_len);
+ for(size_t i = 0; i != buf_len; ++i)
+ {
+ if(isprint(buf[i]))
+ printf("%c", buf[i]);
+ }
+ printf("\n");
+
+ read_queue.write(buf, buf_len);
}
+
+ std::function<size_t (byte[], size_t)> input_fn;
+ TLS::Server server;
+ SecureQueue read_queue;
+ bool exit;
};
int main(int argc, char* argv[])
@@ -40,59 +147,82 @@ int main(int argc, char* argv[])
try
{
LibraryInitializer botan_init;
- SocketInitializer socket_init;
+ //SocketInitializer socket_init;
AutoSeeded_RNG rng;
- //RSA_PrivateKey key(rng, 1024);
- DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024"));
+ Server_Socket listener(port);
- X509_Cert_Options options(
- "localhost/US/Syn Ack Labs/Mathematical Munitions Dept");
+ TLS::Policy policy;
- X509_Certificate cert =
- X509::create_self_signed_cert(options, key, "SHA-1", rng);
+ TLS::Session_Manager_In_Memory sessions;
- Server_Socket listener(port);
+ Credentials_Manager_Simple creds(rng);
- Server_TLS_Policy policy;
+ std::vector<std::string> protocols;
+
+ /*
+ * These are the protocols we advertise to the client, but the
+ * client will send back whatever it actually plans on talking,
+ * which may or may not take into account what we advertise.
+ */
+ protocols.push_back("echo/1.0");
+ protocols.push_back("echo/1.1");
while(true)
{
try {
printf("Listening for new connection on port %d\n", port);
- Socket* sock = listener.accept();
+ std::auto_ptr<Socket> sock(listener.accept());
printf("Got new connection\n");
- TLS_Server 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,
- cert,
- key);
+ Blocking_TLS_Server tls(
+ std::bind(&Socket::write, std::ref(sock), _1, _2),
+ std::bind(&Socket::read, std::ref(sock), _1, _2, true),
+ protocols,
+ sessions,
+ creds,
+ policy,
+ rng);
- std::string hostname = tls.requested_hostname();
+ const char* msg = "Welcome to the best echo server evar\n";
+ tls.write((const Botan::byte*)msg, strlen(msg));
- if(hostname != "")
- printf("Client requested host '%s'\n", hostname.c_str());
+ std::string line;
- printf("Writing some text\n");
+ while(tls.is_active())
+ {
+ byte b;
+ size_t got = tls.read(&b, 1);
- char msg[] = "Foo\nBar\nBaz\nQuux\n";
- tls.write((const Botan::byte*)msg, strlen(msg));
+ if(got == 0)
+ break;
+
+ line += (char)b;
+ if(b == '\n')
+ {
+ //std::cout << line;
+
+ tls.write(reinterpret_cast<const byte*>(line.data()), line.size());
- printf("Now trying a read...\n");
+ if(line == "quit\n")
+ {
+ tls.close();
+ break;
+ }
- char buf[1024] = { 0 };
- u32bit got = tls.read((Botan::byte*)buf, sizeof(buf)-1);
- printf("%d: '%s'\n", got, buf);
+ if(line == "reneg\n")
+ tls.underlying().renegotiate(false);
+ else if(line == "RENEG\n")
+ tls.underlying().renegotiate(true);
- tls.close();
+ line.clear();
+ }
+ }
}
- catch(std::exception& e) { printf("%s\n", e.what()); }
+ catch(std::exception& e) { printf("Connection problem: %s\n", e.what()); }
}
}
catch(std::exception& e)
diff --git a/doc/examples/tss.cpp b/doc/examples/tss.cpp
index 03d7699bf..aecf95796 100644
--- a/doc/examples/tss.cpp
+++ b/doc/examples/tss.cpp
@@ -11,7 +11,7 @@
namespace {
-void print(const Botan::SecureVector<Botan::byte>& r)
+void print(const Botan::secure_vector<Botan::byte>& r)
{
for(Botan::u32bit i = 0; i != r.size(); ++i)
printf("%02X", r[i]);
diff --git a/doc/index.txt b/doc/index.txt
index 75e2ca434..33de06f55 100644
--- a/doc/index.txt
+++ b/doc/index.txt
@@ -4,7 +4,7 @@ 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>`,
+<algos>` you might be looking for, along with :doc:`SSL/TLS <tls>`,
: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
diff --git a/doc/log.txt b/doc/log.txt
index 478b27a94..180a50340 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -10,10 +10,21 @@ Series 1.10
Version 1.10.2, Not Yet Released
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* Pipe::reset no longer requires that message processing be completed,
+ a requirement that caused problems when a Filter's end_msg call
+ threw an exception, after which point the Pipe object was no longer
+ usable.
+
* The SSL/TLS code is disabled by default in this release. A new
version is being developed and the current iteration should not be
used unless needed for existing code.
+* Add support for the rdrand instruction introduced in Intel's Ivy
+ Bridge processors.
+
+* CPUID::has_rdrand was checking the wrong cpuid bit, and would false
+ positive on AMD Bulldozer processors.
+
* Add the Camellia block cipher
* An implementation of SRP-6a compatible with the specification in
@@ -34,6 +45,9 @@ Version 1.10.2, Not Yet Released
* Add Google's Native Client as an compile target
+* The Qt mutex wrapper was broken and would not compile with any recent
+ version of Qt. It has been removed.
+
* If targetting GCC on a Windows system, configure.py will warn that
likely you wanted to configure for either MinGW or Cygwin, not the
generic Windows target which is oriented to Win32 plus the Visual
diff --git a/doc/ssl.txt b/doc/ssl.txt
deleted file mode 100644
index f536b7198..000000000
--- a/doc/ssl.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-
-.. _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/tls.txt b/doc/tls.txt
new file mode 100644
index 000000000..267fb6e62
--- /dev/null
+++ b/doc/tls.txt
@@ -0,0 +1,151 @@
+
+.. _tls_api:
+
+SSL and TLS
+========================================
+
+.. versionadded:: 1.10.2
+
+Botan supports both client and server implementations of the SSL/TLS
+protocols, including SSL v3, TLS v1.0, TLS v1.1, and TLS v1.2 (the
+insecure and obsolete SSL v2 protocol is not supported, beyond
+processing SSL v2 client hellos which some clients still send for
+backwards compatability with ancient servers).
+
+The implementation uses ``std::tr1::function`` for callbacks, so it
+may not have been compiled into the version you are using; you can
+test for the feature macro ``BOTAN_HAS_TLS`` to check.
+
+General TLS Interface
+----------------------------------------
+
+TLS servers and clients share most of an interface, called
+`TLS_Channel`. The primary difference is in terms of how the objects
+are constructed. A TLS channel (either client or server object) has
+these methods available:
+
+.. cpp:class:: TLS_Channel
+
+ .. cpp:function size_t received_data(const byte buf[], size_t buf_size)
+
+ This function is used to provide data sent by the counterparty (eg
+ data that you read off the socket layer). Depending on the current
+ protocol state and the amount of data provided this may result in one
+ or more callback functions that were provided to the constructor being
+ called.
+
+ .. cpp:function void send(const byte buf[], size_t buf_size)
+
+ If the connection has completed the initial handshake process, the
+ data provided is sent to the counterparty as TLS
+ traffic. Otherwise, an exception is thrown.
+
+ .. cpp:function:: void close()
+
+ A close notification is sent to the counterparty, and the internal
+ state is cleared.
+
+ .. cpp:function:: bool is_active()
+
+ Returns true if and only if a handshake has been completed on this
+ connection.
+
+ .. cpp:function:: bool is_closed()
+
+ Returns true if and only if a close notification has been sent or
+ received, or if a fatal alert of any kind was received from the
+ counterparty.
+
+ .. cpp:function:: void renegotiate()
+
+ Initiates a renegotiation. The counterparty is allowed by the
+ protocol to ignore this request. If a successful renegotiation
+ occurs, the *handshake_complete* callback will be called again.
+
+ .. cpp:function:: std::vector<X509_Certificate> peer_cert_chain()
+
+ Returns the certificate chain of the server
+
+
+
+TLS Clients
+----------------------------------------
+
+.. cpp:class:: TLS_Client
+
+ .. cpp:function:: TLS_Client( \
+ std::tr1::function<void, const byte*, size_t> socket_output_fn, \
+ std::tr1::function<void, const byte*, size_t, u16bit> proc_fn, \
+ std::tr1::function<bool, const TLS_Session&> handshake_complete, \
+ TLS_Session_Manager& session_manager, \
+ Credentials_Manager& credendials_manager, \
+ const TLS_Policy& policy, \
+ RandomNumberGenerator& rng, \
+ const std::string& servername = "", \
+ std::tr1::function<std::string, std::vector<std::string> > next_protocol)
+
+ Initialize a new TLS client. The constructor will immediately
+ initiate a new session. The *socket_output_fn* callback will be
+ called with output that should be sent to the counterparty.
+
+ The *proc_fn* will be called with data sent by the counterparty
+ after it has been processed. The byte array and size_t represent
+ the plaintext; the u16bit value provides notification if the
+ counterparty sent an alert via the TLS alert system. Possible values
+ of alert data are included in the Alert_Type enum. Particularly
+ relevant is the CLOSE_NOTIFY value.
+
+ The *handshake_complete* function is called when a handshake
+ (either initial or renegotiation) is completed. The return value of
+ the callback specifies if the session should be cached for later
+ resumption. If the function for some reason desires to prevent the
+ connection from completing, it should throw an exception
+ (preferably a TLS_Exception, which can provide more specific alert
+ information to the counterparty).
+
+ The *session_manager* is an interface for storing TLS sessions,
+ which allows for session resumption upon reconnecting to a server.
+ In the absence of a need for persistent sessions, use
+ `TLS_Session_Manager_In_Memory` which caches connections for the
+ lifetime of a single process.
+
+ The *credentials_manager* is an interface that will be called to
+ retrieve any certificates, secret keys, pre-shared keys, or SRP
+ intformation; see :doc:`credentials <credentials_manager>` for more
+ information.
+
+ Use *servername* to specify the DNS name of the server you are
+ attempting to connect to, if you know it.
+
+ The optional *next_protocol* callback is called if the server
+ indicates it supports the next protocol notification extension.
+ The callback wlil be called with a list of protocol names that the
+ server advertises, and the client can select from them or return an
+ unadvertised protocol.
+
+A simple TLS client example:
+
+.. literalinclude:: examples/tls_client.cpp
+
+
+TLS Servers
+----------------------------------------
+
+.. cpp:class:: TLS_Server
+
+ .. cpp:function:: TLS_Server(std::tr1::function<void, const byte*, size_t> socket_output_fn, \
+ std::tr1::function<void, const byte*, size_t, u16bit> proc_fn, \
+ std::tr1::function<bool, const TLS_Session&> handshake_complete, \
+ TLS_Session_Manager& session_manager, \
+ Credentials_Manager& creds, \
+ const TLS_Policy& policy, \
+ RandomNumberGenerator& rng, \
+ const std::vector<std::string>& protocols)
+
+The first 7 arguments are treated similiarly to `TLS_Client`. The
+final (optional) argument, protocols, specifies the protocols the
+server is willing to advertise it supports.
+
+A TLS server that can handle concurrent connections using asio:
+
+.. literalinclude:: examples/asio_tls_server.cpp
diff --git a/src/algo_base/algo_base.h b/src/algo_base/algo_base.h
index 813216a36..f757a9a83 100644
--- a/src/algo_base/algo_base.h
+++ b/src/algo_base/algo_base.h
@@ -19,7 +19,6 @@ namespace Botan {
class BOTAN_DLL Algorithm
{
public:
-
/**
* Zeroize internal state
*/
@@ -31,10 +30,10 @@ class BOTAN_DLL Algorithm
virtual std::string name() const = 0;
Algorithm() {}
+ Algorithm(const Algorithm&) = delete;
+ Algorithm& operator=(const Algorithm&) = delete;
+
virtual ~Algorithm() {}
- private:
- Algorithm(const Algorithm&) {}
- Algorithm& operator=(const Algorithm&) { return (*this); }
};
}
diff --git a/src/algo_base/buf_comp.h b/src/algo_base/buf_comp.h
index 7838571e9..1dd8be992 100644
--- a/src/algo_base/buf_comp.h
+++ b/src/algo_base/buf_comp.h
@@ -10,6 +10,7 @@
#include <botan/secmem.h>
#include <botan/get_byte.h>
+#include <string>
namespace Botan {
@@ -34,9 +35,18 @@ class BOTAN_DLL Buffered_Computation
/**
* Add new input to process.
- * @param in the input to process as a MemoryRegion
+ * @param in the input to process as a secure_vector
*/
- void update(const MemoryRegion<byte>& in)
+ void update(const secure_vector<byte>& in)
+ {
+ add_data(&in[0], in.size());
+ }
+
+ /**
+ * Add new input to process.
+ * @param in the input to process as a std::vector
+ */
+ void update(const std::vector<byte>& in)
{
add_data(&in[0], in.size());
}
@@ -82,11 +92,11 @@ class BOTAN_DLL Buffered_Computation
/**
* Complete the computation and retrieve the
* final result.
- * @return SecureVector holding the result
+ * @return secure_vector holding the result
*/
- SecureVector<byte> final()
+ secure_vector<byte> final()
{
- SecureVector<byte> output(output_length());
+ secure_vector<byte> output(output_length());
final_result(&output[0]);
return output;
}
@@ -98,7 +108,7 @@ class BOTAN_DLL Buffered_Computation
* @param length the length of the byte array
* @result the result of the call to final()
*/
- SecureVector<byte> process(const byte in[], size_t length)
+ secure_vector<byte> process(const byte in[], size_t length)
{
add_data(in, length);
return final();
@@ -110,7 +120,13 @@ class BOTAN_DLL Buffered_Computation
* @param in the input to process
* @result the result of the call to final()
*/
- SecureVector<byte> process(const MemoryRegion<byte>& in)
+ secure_vector<byte> process(const secure_vector<byte>& in)
+ {
+ add_data(&in[0], in.size());
+ return final();
+ }
+
+ secure_vector<byte> process(const std::vector<byte>& in)
{
add_data(&in[0], in.size());
return final();
@@ -122,7 +138,7 @@ class BOTAN_DLL Buffered_Computation
* @param in the input to process as a string
* @result the result of the call to final()
*/
- SecureVector<byte> process(const std::string& in)
+ secure_vector<byte> process(const std::string& in)
{
update(in);
return final();
diff --git a/src/algo_base/symkey.cpp b/src/algo_base/symkey.cpp
index 56648d9c5..52b216361 100644
--- a/src/algo_base/symkey.cpp
+++ b/src/algo_base/symkey.cpp
@@ -26,7 +26,7 @@ OctetString::OctetString(RandomNumberGenerator& rng,
/*
* Create an OctetString from a hex string
*/
-void OctetString::change(const std::string& hex_string)
+OctetString::OctetString(const std::string& hex_string)
{
bits.resize(1 + hex_string.length() / 2);
bits.resize(hex_decode(&bits[0], hex_string));
@@ -35,10 +35,9 @@ void OctetString::change(const std::string& hex_string)
/*
* Create an OctetString from a byte string
*/
-void OctetString::change(const byte in[], size_t n)
+OctetString::OctetString(const byte in[], size_t n)
{
- bits.resize(n);
- bits.copy(in, n);
+ bits.assign(in, in + n);
}
/*
@@ -113,7 +112,7 @@ bool operator!=(const OctetString& s1, const OctetString& s2)
*/
OctetString operator+(const OctetString& k1, const OctetString& k2)
{
- SecureVector<byte> out;
+ secure_vector<byte> out;
out += k1.bits_of();
out += k2.bits_of();
return OctetString(out);
@@ -124,9 +123,10 @@ OctetString operator+(const OctetString& k1, const OctetString& k2)
*/
OctetString operator^(const OctetString& k1, const OctetString& k2)
{
- SecureVector<byte> ret(std::max(k1.length(), k2.length()));
- ret.copy(k1.begin(), k1.length());
- xor_buf(ret, k2.begin(), k2.length());
+ secure_vector<byte> ret(std::max(k1.length(), k2.length()));
+
+ copy_mem(&ret[0], k1.begin(), k1.length());
+ xor_buf(&ret[0], k2.begin(), k2.length());
return OctetString(ret);
}
diff --git a/src/algo_base/symkey.h b/src/algo_base/symkey.h
index 6735b2b87..b47da8a69 100644
--- a/src/algo_base/symkey.h
+++ b/src/algo_base/symkey.h
@@ -25,9 +25,9 @@ class BOTAN_DLL OctetString
size_t length() const { return bits.size(); }
/**
- * @return this object as a SecureVector<byte>
+ * @return this object as a secure_vector<byte>
*/
- SecureVector<byte> bits_of() const { return bits; }
+ secure_vector<byte> bits_of() const { return bits; }
/**
* @return start of this string
@@ -57,23 +57,10 @@ class BOTAN_DLL OctetString
void set_odd_parity();
/**
- * Change the contents of this octet string
- * @param hex_string a hex encoded bytestring
- */
- void change(const std::string& hex_string);
-
- /**
- * Change the contents of this octet string
- * @param in the input
- * @param length of in in bytes
- */
- void change(const byte in[], size_t length);
-
- /**
- * Change the contents of this octet string
- * @param in the input
+ * Create a new OctetString
+ * @param str is a hex encoded string
*/
- void change(const MemoryRegion<byte>& in) { bits = in; }
+ OctetString(const std::string& str = "");
/**
* Create a new random OctetString
@@ -84,24 +71,24 @@ class BOTAN_DLL OctetString
/**
* Create a new OctetString
- * @param str is a hex encoded string
+ * @param in is an array
+ * @param len is the length of in in bytes
*/
- OctetString(const std::string& str = "") { change(str); }
+ OctetString(const byte in[], size_t len);
/**
* Create a new OctetString
- * @param in is an array
- * @param len is the length of in in bytes
+ * @param in a bytestring
*/
- OctetString(const byte in[], size_t len) { change(in, len); }
+ OctetString(const secure_vector<byte>& in) : bits(in) {}
/**
* Create a new OctetString
* @param in a bytestring
*/
- OctetString(const MemoryRegion<byte>& in) { change(in); }
+ OctetString(const std::vector<byte>& in) : bits(&in[0], &in[in.size()]) {}
private:
- SecureVector<byte> bits;
+ secure_vector<byte> bits;
};
/**
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h
index 25f2db023..11a5580fb 100644
--- a/src/algo_factory/algo_cache.h
+++ b/src/algo_factory/algo_cache.h
@@ -8,8 +8,9 @@
#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
-#include <botan/internal/mutex.h>
+#include <botan/types.h>
#include <botan/internal/stl_util.h>
+#include <mutex>
#include <string>
#include <vector>
#include <map>
@@ -67,21 +68,12 @@ class Algorithm_Cache
*/
void clear_cache();
- /**
- * Constructor
- * @param m a mutex to serialize internal access
- */
- Algorithm_Cache(Mutex* m) : mutex(m) {}
- ~Algorithm_Cache() { clear_cache(); delete mutex; }
+ ~Algorithm_Cache() { clear_cache(); }
private:
- typedef typename std::map<std::string, std::map<std::string, T*> >::iterator
- algorithms_iterator;
-
- typedef typename std::map<std::string, T*>::iterator provider_iterator;
+ typename std::map<std::string, std::map<std::string, T*> >::const_iterator
+ find_algorithm(const std::string& algo_spec);
- algorithms_iterator find_algorithm(const std::string& algo_spec);
-
- Mutex* mutex;
+ std::mutex mutex;
std::map<std::string, std::string> aliases;
std::map<std::string, std::string> pref_providers;
std::map<std::string, std::map<std::string, T*> > algorithms;
@@ -92,16 +84,15 @@ class Algorithm_Cache
* Assumes object lock is held
*/
template<typename T>
-typename Algorithm_Cache<T>::algorithms_iterator
+typename std::map<std::string, std::map<std::string, T*> >::const_iterator
Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
{
- algorithms_iterator algo = algorithms.find(algo_spec);
+ auto algo = algorithms.find(algo_spec);
// Not found? Check if a known alias
if(algo == algorithms.end())
{
- std::map<std::string, std::string>::const_iterator alias =
- aliases.find(algo_spec);
+ auto alias = aliases.find(algo_spec);
if(alias != aliases.end())
algo = algorithms.find(alias->second);
@@ -117,28 +108,28 @@ template<typename T>
const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
const std::string& requested_provider)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
- algorithms_iterator algo = find_algorithm(algo_spec);
+ auto algo = find_algorithm(algo_spec);
if(algo == algorithms.end()) // algo not found at all (no providers)
- return 0;
+ return nullptr;
// If a provider is requested specifically, return it or fail entirely
if(requested_provider != "")
{
- provider_iterator prov = algo->second.find(requested_provider);
+ auto prov = algo->second.find(requested_provider);
if(prov != algo->second.end())
return prov->second;
- return 0;
+ return nullptr;
}
- const T* prototype = 0;
+ const T* prototype = nullptr;
std::string prototype_provider;
size_t prototype_prov_weight = 0;
const std::string pref_provider = search_map(pref_providers, algo_spec);
- for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
+ for(auto i = algo->second.begin(); i != algo->second.end(); ++i)
{
const std::string prov_name = i->first;
const size_t prov_weight = static_provider_weight(prov_name);
@@ -147,7 +138,7 @@ const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
if(prov_name == pref_provider)
return i->second;
- if(prototype == 0 || prov_weight > prototype_prov_weight)
+ if(prototype == nullptr || prov_weight > prototype_prov_weight)
{
prototype = i->second;
prototype_provider = i->first;
@@ -169,7 +160,7 @@ void Algorithm_Cache<T>::add(T* algo,
if(!algo)
return;
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
if(algo->name() != requested_name &&
aliases.find(requested_name) == aliases.end())
@@ -189,15 +180,14 @@ void Algorithm_Cache<T>::add(T* algo,
template<typename T> std::vector<std::string>
Algorithm_Cache<T>::providers_of(const std::string& algo_name)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
std::vector<std::string> providers;
- algorithms_iterator algo = find_algorithm(algo_name);
-
+ auto algo = find_algorithm(algo_name);
if(algo != algorithms.end())
{
- provider_iterator provider = algo->second.begin();
+ auto provider = algo->second.begin();
while(provider != algo->second.end())
{
@@ -216,7 +206,7 @@ template<typename T>
void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
const std::string& provider)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
pref_providers[algo_spec] = provider;
}
@@ -227,11 +217,11 @@ void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
template<typename T>
void Algorithm_Cache<T>::clear_cache()
{
- algorithms_iterator algo = algorithms.begin();
+ auto algo = algorithms.begin();
while(algo != algorithms.end())
{
- provider_iterator provider = algo->second.begin();
+ auto provider = algo->second.begin();
while(provider != algo->second.end())
{
diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp
index 3d640ab8a..1683648bd 100644
--- a/src/algo_factory/algo_factory.cpp
+++ b/src/algo_factory/algo_factory.cpp
@@ -30,7 +30,7 @@ template<typename T>
T* engine_get_algo(Engine*,
const SCAN_Name&,
Algorithm_Factory&)
- { return 0; }
+ { return nullptr; }
template<>
BlockCipher* engine_get_algo(Engine* engine,
@@ -75,7 +75,7 @@ const T* factory_prototype(const std::string& algo_spec,
SCAN_Name scan_name(algo_spec);
if(scan_name.cipher_mode() != "")
- return 0;
+ return nullptr;
for(size_t i = 0; i != engines.size(); ++i)
{
@@ -94,13 +94,13 @@ const T* factory_prototype(const std::string& algo_spec,
/*
* Setup caches
*/
-Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf)
+Algorithm_Factory::Algorithm_Factory()
{
- block_cipher_cache = new Algorithm_Cache<BlockCipher>(mf.make());
- stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make());
- hash_cache = new Algorithm_Cache<HashFunction>(mf.make());
- mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make());
- pbkdf_cache = new Algorithm_Cache<PBKDF>(mf.make());
+ block_cipher_cache = new Algorithm_Cache<BlockCipher>();
+ stream_cipher_cache = new Algorithm_Cache<StreamCipher>();
+ hash_cache = new Algorithm_Cache<HashFunction>();
+ mac_cache = new Algorithm_Cache<MessageAuthenticationCode>();
+ pbkdf_cache = new Algorithm_Cache<PBKDF>();
}
/*
@@ -114,7 +114,8 @@ Algorithm_Factory::~Algorithm_Factory()
delete mac_cache;
delete pbkdf_cache;
- std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
+ for(auto i = engines.begin(); i != engines.end(); ++i)
+ delete *i;
}
void Algorithm_Factory::clear_caches()
@@ -156,7 +157,7 @@ void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec,
Engine* Algorithm_Factory::get_engine_n(size_t n) const
{
if(n >= engines.size())
- return 0;
+ return nullptr;
return engines[n];
}
diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h
index b9f15757d..1bec2adf7 100644
--- a/src/algo_factory/algo_factory.h
+++ b/src/algo_factory/algo_factory.h
@@ -26,7 +26,6 @@ class PBKDF;
template<typename T> class Algorithm_Cache;
class Engine;
-class Mutex_Factory;
/**
* Algorithm Factory
@@ -38,7 +37,7 @@ class BOTAN_DLL Algorithm_Factory
* Constructor
* @param mf a mutex factory
*/
- Algorithm_Factory(Mutex_Factory& mf);
+ Algorithm_Factory();
/**
* Destructor
diff --git a/src/algo_factory/info.txt b/src/algo_factory/info.txt
index eae4b3934..236fdda0e 100644
--- a/src/algo_factory/info.txt
+++ b/src/algo_factory/info.txt
@@ -20,6 +20,5 @@ block
engine
hash
mac
-mutex
stream
</requires>
diff --git a/src/alloc/alloc_mmap/info.txt b/src/alloc/alloc_mmap/info.txt
deleted file mode 100644
index 562277a37..000000000
--- a/src/alloc/alloc_mmap/info.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-define ALLOC_MMAP
-
-<source>
-mmap_mem.cpp
-</source>
-
-<header:internal>
-mmap_mem.h
-</header:internal>
-
-<os>
-linux
-freebsd
-dragonfly
-openbsd
-netbsd
-solaris
-qnx
-darwin
-tru64
-
-# Only without -ansi, otherwise can't get mkstemp
-#cygwin
-</os>
-
-<requires>
-mem_pool
-</requires>
diff --git a/src/alloc/alloc_mmap/mmap_mem.cpp b/src/alloc/alloc_mmap/mmap_mem.cpp
deleted file mode 100644
index e4b602764..000000000
--- a/src/alloc/alloc_mmap/mmap_mem.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-* Memory Mapping Allocator
-* (C) 1999-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mmap_mem.h>
-#include <vector>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifndef MAP_FAILED
- #define MAP_FAILED -1
-#endif
-
-namespace Botan {
-
-namespace {
-
-/*
-* MemoryMapping_Allocator Exception
-*/
-class BOTAN_DLL MemoryMapping_Failed : public Exception
- {
- public:
- MemoryMapping_Failed(const std::string& msg) :
- Exception("MemoryMapping_Allocator: " + msg) {}
- };
-
-}
-
-/*
-* Memory Map a File into Memory
-*/
-void* MemoryMapping_Allocator::alloc_block(size_t n)
- {
- class TemporaryFile
- {
- public:
- int get_fd() const { return fd; }
-
- TemporaryFile(const std::string& base)
- {
- const std::string mkstemp_template = base + "XXXXXX";
-
- std::vector<char> filepath(mkstemp_template.begin(),
- mkstemp_template.end());
- filepath.push_back(0); // add terminating NULL
-
- mode_t old_umask = ::umask(077);
- fd = ::mkstemp(&filepath[0]);
- ::umask(old_umask);
-
- if(fd == -1)
- throw MemoryMapping_Failed("Temporary file allocation failed");
-
- if(::unlink(&filepath[0]) != 0)
- throw MemoryMapping_Failed("Could not unlink temporary file");
- }
-
- ~TemporaryFile()
- {
- /*
- * We can safely close here, because post-mmap the file
- * will continue to exist until the mmap is unmapped from
- * our address space upon deallocation (or process exit).
- */
- if(fd != -1 && ::close(fd) == -1)
- throw MemoryMapping_Failed("Could not close file");
- }
- private:
- int fd;
- };
-
- TemporaryFile file("/tmp/botan_");
-
- if(file.get_fd() == -1)
- throw MemoryMapping_Failed("Could not create file");
-
- std::vector<byte> zeros(4096);
-
- size_t remaining = n;
-
- while(remaining)
- {
- const size_t write_try = std::min(zeros.size(), remaining);
-
- 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_got;
- }
-
-#ifndef MAP_NOSYNC
- #define MAP_NOSYNC 0
-#endif
-
- void* ptr = ::mmap(0, n,
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_NOSYNC,
- file.get_fd(), 0);
-
- if(ptr == static_cast<void*>(MAP_FAILED))
- throw MemoryMapping_Failed("Could not map file");
-
- return ptr;
- }
-
-/*
-* Remove a Memory Mapping
-*/
-void MemoryMapping_Allocator::dealloc_block(void* ptr, size_t n)
- {
- if(ptr == 0)
- return;
-
- const byte PATTERNS[] = { 0x00, 0xF5, 0x5A, 0xAF, 0x00 };
-
- for(size_t i = 0; i != sizeof(PATTERNS); ++i)
- {
- std::memset(ptr, PATTERNS[i], n);
-
- if(::msync((char*)ptr, n, MS_SYNC))
- throw MemoryMapping_Failed("Sync operation failed");
- }
-
- if(::munmap((char*)ptr, n))
- throw MemoryMapping_Failed("Could not unmap file");
- }
-
-}
diff --git a/src/alloc/alloc_mmap/mmap_mem.h b/src/alloc/alloc_mmap/mmap_mem.h
deleted file mode 100644
index fa4e5e715..000000000
--- a/src/alloc/alloc_mmap/mmap_mem.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-* Memory Mapping Allocator
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MMAP_ALLOCATOR_H__
-#define BOTAN_MMAP_ALLOCATOR_H__
-
-#include <botan/internal/mem_pool.h>
-
-namespace Botan {
-
-/**
-* Allocator that uses memory maps backed by disk. We zeroize the map
-* upon deallocation. If swap occurs, the VM will swap to the shared
-* file backing rather than to a swap device, which means we know where
-* it is and can zap it later.
-*/
-class MemoryMapping_Allocator : public Pooling_Allocator
- {
- public:
- /**
- * @param mutex used for internal locking
- */
- MemoryMapping_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {}
- std::string type() const { return "mmap"; }
- private:
- void* alloc_block(size_t);
- void dealloc_block(void*, size_t);
- };
-
-}
-
-#endif
diff --git a/src/alloc/allocate.h b/src/alloc/allocate.h
deleted file mode 100644
index b8574be1e..000000000
--- a/src/alloc/allocate.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-* Allocator
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_ALLOCATOR_H__
-#define BOTAN_ALLOCATOR_H__
-
-#include <botan/types.h>
-#include <string>
-
-namespace Botan {
-
-/**
-* Allocator Interface
-*/
-class BOTAN_DLL Allocator
- {
- public:
- /**
- * Acquire a pointer to an allocator
- * @param locking is true if the allocator should attempt to
- * secure the memory (eg for using to store keys)
- * @return pointer to an allocator; ownership remains with library,
- * so do not delete
- */
- static Allocator* get(bool locking);
-
- /**
- * Allocate a block of memory
- * @param n how many bytes to allocate
- * @return pointer to n bytes of memory
- */
- virtual void* allocate(size_t n) = 0;
-
- /**
- * Deallocate memory allocated with allocate()
- * @param ptr the pointer returned by allocate()
- * @param n the size of the block pointed to by ptr
- */
- virtual void deallocate(void* ptr, size_t n) = 0;
-
- /**
- * @return name of this allocator type
- */
- virtual std::string type() const = 0;
-
- /**
- * Initialize the allocator
- */
- virtual void init() {}
-
- /**
- * Shutdown the allocator
- */
- virtual void destroy() {}
-
- virtual ~Allocator() {}
- };
-
-}
-
-#endif
diff --git a/src/alloc/info.txt b/src/alloc/info.txt
index 40e7bacdf..0ab7fa768 100644
--- a/src/alloc/info.txt
+++ b/src/alloc/info.txt
@@ -1,4 +1,3 @@
<header:public>
-allocate.h
secmem.h
</header:public>
diff --git a/src/alloc/locking_allocator/info.txt b/src/alloc/locking_allocator/info.txt
new file mode 100644
index 000000000..34877e6bd
--- /dev/null
+++ b/src/alloc/locking_allocator/info.txt
@@ -0,0 +1 @@
+define LOCKING_ALLOCATOR
diff --git a/src/alloc/locking_allocator/locking_allocator.cpp b/src/alloc/locking_allocator/locking_allocator.cpp
new file mode 100644
index 000000000..cc7d24c8d
--- /dev/null
+++ b/src/alloc/locking_allocator/locking_allocator.cpp
@@ -0,0 +1,236 @@
+/*
+* Mlock Allocator
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/locking_allocator.h>
+#include <botan/internal/assert.h>
+#include <algorithm>
+#include <cstring>
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+namespace Botan {
+
+namespace {
+
+size_t mlock_limit()
+ {
+ struct rlimit limits;
+ ::getrlimit(RLIMIT_MEMLOCK, &limits);
+
+ if(limits.rlim_cur < limits.rlim_max)
+ {
+ limits.rlim_cur = limits.rlim_max;
+ ::setrlimit(RLIMIT_MEMLOCK, &limits);
+ ::getrlimit(RLIMIT_MEMLOCK, &limits);
+ }
+
+ /*
+ * Linux defaults to only 64 KiB of mlockable memory per process
+ * (too small) but BSDs offer a small fraction of total RAM (more
+ * than we need). Bound the total mlock size to 256 KiB which is
+ * enough to run the entire test suite without spilling to non-mlock
+ * memory, but small enough that we should not cause problems if
+ * multiple processes are mlocking on the same machine.
+ */
+ return std::min<size_t>(limits.rlim_cur, 256*1024);
+ }
+
+bool ptr_in_pool(const void* pool_ptr, size_t poolsize,
+ const void* buf_ptr, size_t bufsize)
+ {
+ const size_t pool = reinterpret_cast<size_t>(pool_ptr);
+ const size_t buf = reinterpret_cast<size_t>(buf_ptr);
+
+ if(buf < pool || buf >= pool + poolsize)
+ return false;
+
+ BOTAN_ASSERT(buf + bufsize <= pool + poolsize,
+ "Invalid pointer/length halfway into mem pool");
+
+ return true;
+ }
+
+size_t padding_for_alignment(size_t offset, size_t desired_alignment)
+ {
+ size_t mod = offset % desired_alignment;
+ if(mod == 0)
+ return 0; // already right on
+ return desired_alignment - mod;
+ }
+
+}
+
+void* mlock_allocator::allocate(size_t n, size_t alignment)
+ {
+ if(!m_pool || n >= m_poolsize)
+ return nullptr; // bigger than the whole pool!
+
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ auto best_fit = m_freelist.end();
+
+ for(auto i = m_freelist.begin(); i != m_freelist.end(); ++i)
+ {
+ // If we have a perfect fit, use it immediately
+ if(i->second == n && (i->first % alignment) == 0)
+ {
+ const size_t offset = i->first;
+ m_freelist.erase(i);
+ ::memset(m_pool + offset, 0, n);
+
+ BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset) % alignment == 0,
+ "Returning correctly aligned pointer");
+
+ return m_pool + offset;
+ }
+
+ if((i->second >= (n + padding_for_alignment(i->first, alignment)) &&
+ ((best_fit == m_freelist.end()) || (best_fit->second > i->second))))
+ {
+ best_fit = i;
+ }
+ }
+
+ if(best_fit != m_freelist.end())
+ {
+ const size_t offset = best_fit->first;
+
+ const size_t alignment_padding = padding_for_alignment(offset, alignment);
+
+ best_fit->first += n + alignment_padding;
+ best_fit->second -= n + alignment_padding;
+
+ // Need to realign, split the block
+ if(alignment_padding)
+ {
+ /*
+ If we used the entire block except for small piece used for
+ alignment at the beginning, so just update the entry already
+ in place (as it is in the correct location), rather than
+ deleting the empty range and inserting the new one in the
+ same location.
+ */
+ if(best_fit->second == 0)
+ {
+ best_fit->first = offset;
+ best_fit->second = alignment_padding;
+ }
+ else
+ m_freelist.insert(best_fit, std::make_pair(offset, alignment_padding));
+ }
+
+ ::memset(m_pool + offset + alignment_padding, 0, n);
+
+ BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset + alignment_padding) % alignment == 0,
+ "Returning correctly aligned pointer");
+
+ return m_pool + offset + alignment_padding;
+ }
+
+ return nullptr;
+ }
+
+bool mlock_allocator::deallocate(void* p, size_t n)
+ {
+ if(!m_pool || !ptr_in_pool(m_pool, m_poolsize, p, n))
+ return false;
+
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ const size_t start = static_cast<byte*>(p) - m_pool;
+
+ auto comp = [](std::pair<size_t, size_t> x, std::pair<size_t, size_t> y){ return x.first < y.first; };
+
+ auto i = std::lower_bound(m_freelist.begin(), m_freelist.end(),
+ std::make_pair(start, 0), comp);
+
+ // try to merge with later block
+ if(i != m_freelist.end() && start + n == i->first)
+ {
+ i->first = start;
+ i->second += n;
+ n = 0;
+ }
+
+ // try to merge with previous block
+ if(i != m_freelist.begin())
+ {
+ auto prev = std::prev(i);
+
+ if(prev->first + prev->second == start)
+ {
+ if(n)
+ {
+ prev->second += n;
+ n = 0;
+ }
+ else
+ {
+ // merge adjoining
+ prev->second += i->second;
+ m_freelist.erase(i);
+ }
+ }
+ }
+
+ if(n != 0) // no merge possible?
+ m_freelist.insert(i, std::make_pair(start, n));
+
+ return true;
+ }
+
+mlock_allocator::mlock_allocator() :
+ m_poolsize(mlock_limit()),
+ m_pool(nullptr)
+ {
+#if !defined(MAP_NOCORE)
+ #define MAP_NOCORE 0
+#endif
+
+ if(m_poolsize)
+ {
+ m_pool = static_cast<byte*>(
+ ::mmap(
+ nullptr, m_poolsize,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_SHARED | MAP_NOCORE,
+ -1, 0));
+
+ if(m_pool == static_cast<byte*>(MAP_FAILED))
+ throw std::runtime_error("Failed to mmap pool");
+
+ std::memset(m_pool, 0x00, m_poolsize);
+
+ if(::mlock(m_pool, m_poolsize) != 0)
+ {
+ ::munmap(m_pool, m_poolsize);
+ m_pool = nullptr;
+ throw std::runtime_error("Failed to lock pool");
+ }
+
+ m_freelist.push_back(std::make_pair(0, m_poolsize));
+ }
+ }
+
+mlock_allocator::~mlock_allocator()
+ {
+ if(m_pool)
+ {
+ std::memset(m_pool, 0, m_poolsize);
+ ::munlock(m_pool, m_poolsize);
+ ::munmap(m_pool, m_poolsize);
+ m_pool = nullptr;
+ }
+ }
+
+mlock_allocator& mlock_allocator::instance()
+ {
+ static mlock_allocator mlock;
+ return mlock;
+ }
+
+}
diff --git a/src/alloc/locking_allocator/locking_allocator.h b/src/alloc/locking_allocator/locking_allocator.h
new file mode 100644
index 000000000..2c756fcd1
--- /dev/null
+++ b/src/alloc/locking_allocator/locking_allocator.h
@@ -0,0 +1,39 @@
+/*
+* Mlock Allocator
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MLOCK_ALLOCATOR_H__
+#define BOTAN_MLOCK_ALLOCATOR_H__
+
+#include <botan/types.h>
+#include <vector>
+#include <mutex>
+
+namespace Botan {
+
+class BOTAN_DLL mlock_allocator
+ {
+ public:
+ static mlock_allocator& instance();
+
+ void* allocate(size_t n, size_t alignment);
+
+ bool deallocate(void* p, size_t n);
+
+ private:
+ mlock_allocator();
+
+ ~mlock_allocator();
+
+ std::mutex m_mutex;
+ size_t m_poolsize;
+ std::vector<std::pair<size_t, size_t>> m_freelist;
+ byte* m_pool;
+ };
+
+}
+
+#endif
diff --git a/src/alloc/mem_pool/info.txt b/src/alloc/mem_pool/info.txt
deleted file mode 100644
index 5097c325f..000000000
--- a/src/alloc/mem_pool/info.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-
-<source>
-mem_pool.cpp
-</source>
-
-<header:internal>
-mem_pool.h
-</header:internal>
-
-<requires>
-mutex
-</requires>
diff --git a/src/alloc/mem_pool/mem_pool.cpp b/src/alloc/mem_pool/mem_pool.cpp
deleted file mode 100644
index f32eb9604..000000000
--- a/src/alloc/mem_pool/mem_pool.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
-* Pooling Allocator
-* (C) 1999-2008 Jack Lloyd
-* 2005 Matthew Gregan
-* 2005-2006 Matt Johnston
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mem_pool.h>
-#include <botan/internal/rounding.h>
-#include <botan/mem_ops.h>
-#include <algorithm>
-#include <exception>
-
-namespace Botan {
-
-/*
-* Memory_Block Constructor
-*/
-Pooling_Allocator::Memory_Block::Memory_Block(void* buf)
- {
- buffer = static_cast<byte*>(buf);
- bitmap = 0;
- buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE);
- }
-
-/*
-* See if ptr is contained by this block
-*/
-bool Pooling_Allocator::Memory_Block::contains(void* ptr,
- size_t length) const
- {
- return ((buffer <= ptr) &&
- (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE));
- }
-
-/*
-* Allocate some memory, if possible
-*/
-byte* Pooling_Allocator::Memory_Block::alloc(size_t n)
- {
- if(n == 0 || n > BITMAP_SIZE)
- return 0;
-
- if(n == BITMAP_SIZE)
- {
- if(bitmap)
- return 0;
- else
- {
- bitmap = ~bitmap;
- return buffer;
- }
- }
-
- bitmap_type mask = (static_cast<bitmap_type>(1) << n) - 1;
- size_t offset = 0;
-
- while(bitmap & mask)
- {
- mask <<= 1;
- ++offset;
-
- if((bitmap & mask) == 0)
- break;
- if(mask >> 63)
- break;
- }
-
- if(bitmap & mask)
- return 0;
-
- bitmap |= mask;
- return buffer + offset * BLOCK_SIZE;
- }
-
-/*
-* Mark this memory as free, if we own it
-*/
-void Pooling_Allocator::Memory_Block::free(void* ptr, size_t blocks)
- {
- clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE);
-
- const size_t offset = (static_cast<byte*>(ptr) - buffer) / BLOCK_SIZE;
-
- if(offset == 0 && blocks == BITMAP_SIZE)
- bitmap = ~bitmap;
- else
- {
- for(size_t j = 0; j != blocks; ++j)
- bitmap &= ~(static_cast<bitmap_type>(1) << (j+offset));
- }
- }
-
-/*
-* Pooling_Allocator Constructor
-*/
-Pooling_Allocator::Pooling_Allocator(Mutex* m) : mutex(m)
- {
- last_used = blocks.begin();
- }
-
-/*
-* Pooling_Allocator Destructor
-*/
-Pooling_Allocator::~Pooling_Allocator()
- {
- delete mutex;
- if(blocks.size())
- throw Invalid_State("Pooling_Allocator: Never released memory");
- }
-
-/*
-* Free all remaining memory
-*/
-void Pooling_Allocator::destroy()
- {
- Mutex_Holder lock(mutex);
-
- blocks.clear();
-
- for(size_t j = 0; j != allocated.size(); ++j)
- dealloc_block(allocated[j].first, allocated[j].second);
- allocated.clear();
- }
-
-/*
-* Allocation
-*/
-void* Pooling_Allocator::allocate(size_t n)
- {
- const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
- const size_t BLOCK_SIZE = Memory_Block::block_size();
-
- Mutex_Holder lock(mutex);
-
- if(n <= BITMAP_SIZE * BLOCK_SIZE)
- {
- const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
-
- byte* mem = allocate_blocks(block_no);
- if(mem)
- return mem;
-
- get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE);
-
- mem = allocate_blocks(block_no);
- if(mem)
- return mem;
-
- throw Memory_Exhaustion();
- }
-
- void* new_buf = alloc_block(n);
- if(new_buf)
- return new_buf;
-
- throw Memory_Exhaustion();
- }
-
-/*
-* Deallocation
-*/
-void Pooling_Allocator::deallocate(void* ptr, size_t n)
- {
- const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
- const size_t BLOCK_SIZE = Memory_Block::block_size();
-
- if(ptr == 0 && n == 0)
- return;
-
- Mutex_Holder lock(mutex);
-
- if(n > BITMAP_SIZE * BLOCK_SIZE)
- dealloc_block(ptr, n);
- else
- {
- const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
-
- std::vector<Memory_Block>::iterator i =
- std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr));
-
- if(i == blocks.end() || !i->contains(ptr, block_no))
- throw Invalid_State("Pointer released to the wrong allocator");
-
- i->free(ptr, block_no);
- }
- }
-
-/*
-* Try to get some memory from an existing block
-*/
-byte* Pooling_Allocator::allocate_blocks(size_t n)
- {
- if(blocks.empty())
- return 0;
-
- std::vector<Memory_Block>::iterator i = last_used;
-
- do
- {
- byte* mem = i->alloc(n);
- if(mem)
- {
- last_used = i;
- return mem;
- }
-
- ++i;
- if(i == blocks.end())
- i = blocks.begin();
- }
- while(i != last_used);
-
- return 0;
- }
-
-/*
-* Allocate more memory for the pool
-*/
-void Pooling_Allocator::get_more_core(size_t in_bytes)
- {
- const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
- const size_t BLOCK_SIZE = Memory_Block::block_size();
-
- const size_t TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE;
-
- // upper bound on allocation is 1 MiB
- in_bytes = std::min<size_t>(in_bytes, 1024 * 1024);
-
- const size_t in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE;
- const size_t to_allocate = in_blocks * TOTAL_BLOCK_SIZE;
-
- void* ptr = alloc_block(to_allocate);
- if(ptr == 0)
- throw Memory_Exhaustion();
-
- allocated.push_back(std::make_pair(ptr, to_allocate));
-
- for(size_t j = 0; j != in_blocks; ++j)
- {
- byte* byte_ptr = static_cast<byte*>(ptr);
- blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE));
- }
-
- std::sort(blocks.begin(), blocks.end());
- last_used = std::lower_bound(blocks.begin(), blocks.end(),
- Memory_Block(ptr));
- }
-
-}
diff --git a/src/alloc/mem_pool/mem_pool.h b/src/alloc/mem_pool/mem_pool.h
deleted file mode 100644
index 28d4dd903..000000000
--- a/src/alloc/mem_pool/mem_pool.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-* Pooling Allocator
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_POOLING_ALLOCATOR_H__
-#define BOTAN_POOLING_ALLOCATOR_H__
-
-#include <botan/allocate.h>
-#include <botan/exceptn.h>
-#include <botan/internal/mutex.h>
-#include <utility>
-#include <vector>
-
-namespace Botan {
-
-/**
-* Pooling Allocator
-*/
-class Pooling_Allocator : public Allocator
- {
- public:
- void* allocate(size_t);
- void deallocate(void*, size_t);
-
- void destroy();
-
- /**
- * @param mutex used for internal locking
- */
- Pooling_Allocator(Mutex* mutex);
- ~Pooling_Allocator();
- private:
- void get_more_core(size_t);
- byte* allocate_blocks(size_t);
-
- virtual void* alloc_block(size_t) = 0;
- virtual void dealloc_block(void*, size_t) = 0;
-
- class Memory_Block
- {
- public:
- Memory_Block(void*);
-
- static size_t bitmap_size() { return BITMAP_SIZE; }
- static size_t block_size() { return BLOCK_SIZE; }
-
- bool contains(void*, size_t) const;
- byte* alloc(size_t);
- void free(void*, size_t);
-
- bool operator<(const Memory_Block& other) const
- {
- if(buffer < other.buffer && other.buffer < buffer_end)
- return false;
- return (buffer < other.buffer);
- }
- private:
- typedef u64bit bitmap_type;
- static const size_t BITMAP_SIZE = 8 * sizeof(bitmap_type);
- static const size_t BLOCK_SIZE = 64;
-
- bitmap_type bitmap;
- byte* buffer, *buffer_end;
- };
-
- std::vector<Memory_Block> blocks;
- std::vector<Memory_Block>::iterator last_used;
- std::vector<std::pair<void*, size_t> > allocated;
- Mutex* mutex;
- };
-
-}
-
-#endif
diff --git a/src/alloc/secmem.h b/src/alloc/secmem.h
index 6c8a75c44..739ba63a5 100644
--- a/src/alloc/secmem.h
+++ b/src/alloc/secmem.h
@@ -1,6 +1,6 @@
/*
* Secure Memory Buffers
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -8,369 +8,121 @@
#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
#define BOTAN_SECURE_MEMORY_BUFFERS_H__
-#include <botan/allocate.h>
#include <botan/mem_ops.h>
#include <algorithm>
+#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
+ #include <botan/locking_allocator.h>
+#endif
+
namespace Botan {
-/**
-* This class represents variable length memory buffers.
-*/
template<typename T>
-class MemoryRegion
+class secure_allocator
{
public:
- /**
- * Find out the size of the buffer, i.e. how many objects of type T it
- * contains.
- * @return size of the buffer
- */
- size_t size() const { return used; }
-
- /**
- * Find out whether this buffer is empty.
- * @return true if the buffer is empty, false otherwise
- */
- bool empty() const { return (used == 0); }
-
- /**
- * Get a pointer to the first element in the buffer.
- * @return pointer to the first element in the buffer
- */
- operator T* () { return buf; }
-
- /**
- * Get a constant pointer to the first element in the buffer.
- * @return constant pointer to the first element in the buffer
- */
- operator const T* () const { return buf; }
-
- /**
- * Get a pointer to the first element in the buffer.
- * @return pointer to the first element in the buffer
- */
- T* begin() { return buf; }
-
- /**
- * Get a constant pointer to the first element in the buffer.
- * @return constant pointer to the first element in the buffer
- */
- const T* begin() const { return buf; }
-
- /**
- * Get a pointer to the last element in the buffer.
- * @return pointer to the last element in the buffer
- */
- T* end() { return (buf + size()); }
-
- /**
- * Get a constant pointer to the last element in the buffer.
- * @return constant pointer to the last element in the buffer
- */
- const T* end() const { return (buf + size()); }
-
- /**
- * Check two buffers for equality.
- * @return true iff the content of both buffers is byte-wise equal
- */
- bool operator==(const MemoryRegion<T>& other) const
- {
- return (size() == other.size() &&
- same_mem(buf, other.buf, size()));
- }
+ typedef T value_type;
- /**
- * Compare two buffers
- * @return true iff this is ordered before other
- */
- bool operator<(const MemoryRegion<T>& other) const;
-
- /**
- * Check two buffers for inequality.
- * @return false if the content of both buffers is byte-wise equal, true
- * otherwise.
- */
- bool operator!=(const MemoryRegion<T>& other) const
- { return (!(*this == other)); }
-
- /**
- * Copy the contents of another buffer into this buffer.
- * The former contents of *this are discarded.
- * @param other the buffer to copy the contents from.
- * @return reference to *this
- */
- MemoryRegion<T>& operator=(const MemoryRegion<T>& other)
- {
- if(this != &other)
- {
- this->resize(other.size());
- this->copy(&other[0], other.size());
- }
- return (*this);
- }
+ typedef T* pointer;
+ typedef const T* const_pointer;
+
+ typedef T& reference;
+ typedef const T& const_reference;
- /**
- * Copy the contents of an array of objects of type T into this buffer.
- * The former contents of *this are discarded.
- * The length of *this must be at least n, otherwise memory errors occur.
- * @param in the array to copy the contents from
- * @param n the length of in
- */
- void copy(const T in[], size_t n)
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ secure_allocator() noexcept {}
+
+ ~secure_allocator() noexcept {}
+
+ pointer address(reference x) const noexcept
+ { return std::addressof(x); }
+
+ const_pointer address(const_reference x) const noexcept
+ { return std::addressof(x); }
+
+ pointer allocate(size_type n, const void* = 0)
{
- copy_mem(buf, in, std::min(n, size()));
+#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
+ if(pointer p = static_cast<pointer>(mlock_allocator::instance().allocate(n*sizeof(T), sizeof(T))))
+ return p;
+#endif
+
+ pointer p = new T[n];
+ clear_mem(p, n);
+ return p;
}
- /**
- * Copy the contents of an array of objects of type T into this buffer.
- * The former contents of *this are discarded.
- * The length of *this must be at least n, otherwise memory errors occur.
- * @param off the offset position inside this buffer to start inserting
- * the copied bytes
- * @param in the array to copy the contents from
- * @param n the length of in
- */
- void copy(size_t off, const T in[], size_t n)
+ void deallocate(pointer p, size_type n)
{
- copy_mem(buf + off, in, std::min(n, size() - off));
+ clear_mem(p, n);
+
+#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
+ if(mlock_allocator::instance().deallocate(p, n*sizeof(T)))
+ return;
+#endif
+
+ delete [] p;
}
- /**
- * Append a single element.
- * @param x the element to append
- */
- void push_back(T x)
+ size_type max_size() const noexcept
{
- resize(size() + 1);
- buf[size()-1] = x;
+ return static_cast<size_type>(-1) / sizeof(T);
}
- /**
- * Reset this buffer to an empty buffer with size zero.
- */
- void clear() { resize(0); }
-
- /**
- * Inserts or erases elements at the end such that the size
- * becomes n, leaving elements in the range 0...n unmodified if
- * set or otherwise zero-initialized
- * @param n length of the new buffer
- */
- void resize(size_t n);
-
- /**
- * Swap this buffer with another object.
- */
- void swap(MemoryRegion<T>& other);
-
- virtual ~MemoryRegion() { deallocate(buf, allocated); }
- protected:
- MemoryRegion() : buf(0), used(0), allocated(0), alloc(0) {}
-
- /**
- * Copy constructor
- * @param other the other region to copy
- */
- MemoryRegion(const MemoryRegion<T>& other)
+ template<typename U, typename... Args>
+ void construct(U* p, Args&&... args)
{
- buf = 0;
- used = allocated = 0;
- alloc = other.alloc;
- resize(other.size());
- copy(&other[0], other.size());
+ ::new(static_cast<void*>(p)) U(std::forward<Args>(args)...);
}
- /**
- * @param locking should we use a locking allocator
- * @param length the initial length to use
- */
- void init(bool locking, size_t length = 0)
- { alloc = Allocator::get(locking); resize(length); }
+ template<typename U> void destroy(U* p) { p->~U(); }
+ };
- private:
- T* allocate(size_t n)
- {
- return static_cast<T*>(alloc->allocate(sizeof(T)*n));
- }
+template<typename T> inline bool
+operator==(const secure_allocator<T>&, const secure_allocator<T>&)
+ { return true; }
- void deallocate(T* p, size_t n)
- { if(alloc && p && n) alloc->deallocate(p, sizeof(T)*n); }
+template<typename T> inline bool
+operator!=(const secure_allocator<T>&, const secure_allocator<T>&)
+ { return false; }
- T* buf;
- size_t used;
- size_t allocated;
- Allocator* alloc;
- };
+template<typename T> using secure_vector = std::vector<T, secure_allocator<T>>;
-/*
-* Change the size of the buffer
-*/
template<typename T>
-void MemoryRegion<T>::resize(size_t n)
+std::vector<T> unlock(const secure_vector<T>& in)
{
- if(n <= allocated)
- {
- size_t zap = std::min(used, n);
- clear_mem(buf + zap, allocated - zap);
- used = n;
- }
- else
- {
- T* new_buf = allocate(n);
- copy_mem(new_buf, buf, used);
- deallocate(buf, allocated);
- buf = new_buf;
- allocated = used = n;
- }
+ std::vector<T> out(in.size());
+ copy_mem(&out[0], &in[0], in.size());
+ return out;
}
-/*
-* Compare this buffer with another one
-*/
-template<typename T>
-bool MemoryRegion<T>::operator<(const MemoryRegion<T>& other) const
+template<typename T, typename Alloc>
+size_t buffer_insert(std::vector<T, Alloc>& buf,
+ size_t buf_offset,
+ const T input[],
+ size_t input_length)
{
- const size_t min_size = std::min(size(), other.size());
-
- // This should probably be rewritten to run in constant time
- for(size_t i = 0; i != min_size; ++i)
- {
- if(buf[i] < other[i])
- return true;
- if(buf[i] > other[i])
- return false;
- }
-
- // First min_size bytes are equal, shorter is first
- return (size() < other.size());
+ const size_t to_copy = std::min(input_length, buf.size() - buf_offset);
+ copy_mem(&buf[buf_offset], input, to_copy);
+ return to_copy;
}
-/*
-* Swap this buffer with another one
-*/
-template<typename T>
-void MemoryRegion<T>::swap(MemoryRegion<T>& x)
+template<typename T, typename Alloc, typename Alloc2>
+size_t buffer_insert(std::vector<T, Alloc>& buf,
+ size_t buf_offset,
+ const std::vector<T, Alloc2>& input)
{
- std::swap(buf, x.buf);
- std::swap(used, x.used);
- std::swap(allocated, x.allocated);
- std::swap(alloc, x.alloc);
+ const size_t to_copy = std::min(input.size(), buf.size() - buf_offset);
+ copy_mem(&buf[buf_offset], &input[0], to_copy);
+ return to_copy;
}
-/**
-* This class represents variable length buffers that do not
-* make use of memory locking.
-*/
-template<typename T>
-class MemoryVector : public MemoryRegion<T>
- {
- public:
- /**
- * Copy the contents of another buffer into this buffer.
- * @param in the buffer to copy the contents from
- * @return reference to *this
- */
- MemoryVector<T>& operator=(const MemoryRegion<T>& in)
- {
- if(this != &in)
- {
- this->resize(in.size());
- this->copy(&in[0], in.size());
- }
- return (*this);
- }
-
- /**
- * Create a buffer of the specified length.
- * @param n the length of the buffer to create.
- */
- MemoryVector(size_t n = 0) { this->init(false, n); }
-
- /**
- * Create a buffer with the specified contents.
- * @param in the array containing the data to be initially copied
- * into the newly created buffer
- * @param n the size of the arry in
- */
- MemoryVector(const T in[], size_t n)
- {
- this->init(false);
- this->resize(n);
- this->copy(in, n);
- }
-
- /**
- * Copy constructor.
- */
- MemoryVector(const MemoryRegion<T>& in)
- {
- this->init(false);
- this->resize(in.size());
- this->copy(&in[0], in.size());
- }
- };
-
-/**
-* This class represents variable length buffers using the operating
-* systems capability to lock memory, i.e. keeping it from being
-* swapped out to disk. In this way, a security hole allowing attackers
-* to find swapped out secret keys is closed.
-*/
-template<typename T>
-class SecureVector : public MemoryRegion<T>
- {
- public:
- /**
- * Copy the contents of another buffer into this buffer.
- * @param other the buffer to copy the contents from
- * @return reference to *this
- */
- SecureVector<T>& operator=(const MemoryRegion<T>& other)
- {
- if(this != &other)
- {
- this->resize(other.size());
- this->copy(&other[0], other.size());
- }
- return (*this);
- }
-
- /**
- * Create a buffer of the specified length.
- * @param n the length of the buffer to create.
- */
- SecureVector(size_t n = 0) { this->init(true, n); }
-
- /**
- * Create a buffer with the specified contents.
- * @param in the array containing the data to be initially copied
- * into the newly created buffer
- * @param n the size of the array in
- */
- SecureVector(const T in[], size_t n)
- {
- this->init(true);
- this->resize(n);
- this->copy(&in[0], n);
- }
-
- /**
- * Create a buffer with contents specified contents.
- * @param in the buffer holding the contents that will be
- * copied into the newly created buffer.
- */
- SecureVector(const MemoryRegion<T>& in)
- {
- this->init(true);
- this->resize(in.size());
- this->copy(&in[0], in.size());
- }
- };
-
-template<typename T>
-MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
- const MemoryRegion<T>& in)
+template<typename T, typename Alloc, typename Alloc2>
+std::vector<T, Alloc>&
+operator+=(std::vector<T, Alloc>& out,
+ const std::vector<T, Alloc2>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.size());
@@ -378,17 +130,16 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
return out;
}
-template<typename T>
-MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
- T in)
+template<typename T, typename Alloc>
+std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, T in)
{
out.push_back(in);
return out;
}
-template<typename T, typename L>
-MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
- const std::pair<const T*, L>& in)
+template<typename T, typename Alloc, typename L>
+std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
+ const std::pair<const T*, L>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.second);
@@ -396,9 +147,9 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
return out;
}
-template<typename T, typename L>
-MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
- const std::pair<T*, L>& in)
+template<typename T, typename Alloc, typename L>
+std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
+ const std::pair<T*, L>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.second);
@@ -410,22 +161,12 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
* Zeroise the values; length remains unchanged
* @param vec the vector to zeroise
*/
-template<typename T>
-void zeroise(MemoryRegion<T>& vec)
+template<typename T, typename Alloc>
+void zeroise(std::vector<T, Alloc>& vec)
{
clear_mem(&vec[0], vec.size());
}
}
-namespace std {
-
-template<typename T>
-inline void swap(Botan::MemoryRegion<T>& x, Botan::MemoryRegion<T>& y)
- {
- x.swap(y);
- }
-
-}
-
#endif
diff --git a/src/alloc/system_alloc/defalloc.cpp b/src/alloc/system_alloc/defalloc.cpp
deleted file mode 100644
index 8e178bb14..000000000
--- a/src/alloc/system_alloc/defalloc.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-* Basic Allocators
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/defalloc.h>
-#include <botan/internal/mlock.h>
-#include <botan/libstate.h>
-#include <cstdlib>
-#include <cstring>
-
-namespace Botan {
-
-namespace {
-
-/*
-* Perform Memory Allocation
-*/
-void* do_malloc(size_t n, bool do_lock)
- {
- void* ptr = std::malloc(n);
-
- if(!ptr)
- return 0;
-
- if(do_lock)
- lock_mem(ptr, n);
-
- std::memset(ptr, 0, n);
- return ptr;
- }
-
-/*
-* Perform Memory Deallocation
-*/
-void do_free(void* ptr, size_t n, bool do_lock)
- {
- if(!ptr)
- return;
-
- std::memset(ptr, 0, n);
- if(do_lock)
- unlock_mem(ptr, n);
-
- std::free(ptr);
- }
-
-}
-
-/*
-* Malloc_Allocator's Allocation
-*/
-void* Malloc_Allocator::allocate(size_t n)
- {
- void* ptr = do_malloc(n, false);
- if(!ptr)
- throw Memory_Exhaustion();
- return ptr;
- }
-
-/*
-* Malloc_Allocator's Deallocation
-*/
-void Malloc_Allocator::deallocate(void* ptr, size_t n)
- {
- do_free(ptr, n, false);
- }
-
-/*
-* Locking_Allocator's Allocation
-*/
-void* Locking_Allocator::alloc_block(size_t n)
- {
- return do_malloc(n, true);
- }
-
-/*
-* Locking_Allocator's Deallocation
-*/
-void Locking_Allocator::dealloc_block(void* ptr, size_t n)
- {
- do_free(ptr, n, true);
- }
-
-/*
-* Get an allocator
-*/
-Allocator* Allocator::get(bool locking)
- {
- std::string type = "";
- if(!locking)
- type = "malloc";
-
- Allocator* alloc = global_state().get_allocator(type);
- if(alloc)
- return alloc;
-
- throw Internal_Error("Couldn't find an allocator to use in get_allocator");
- }
-
-}
diff --git a/src/alloc/system_alloc/defalloc.h b/src/alloc/system_alloc/defalloc.h
deleted file mode 100644
index 6fba0e511..000000000
--- a/src/alloc/system_alloc/defalloc.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-* Basic Allocators
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_BASIC_ALLOC_H__
-#define BOTAN_BASIC_ALLOC_H__
-
-#include <botan/internal/mem_pool.h>
-
-namespace Botan {
-
-/**
-* Allocator using malloc
-*/
-class Malloc_Allocator : public Allocator
- {
- public:
- void* allocate(size_t);
- void deallocate(void*, size_t);
-
- std::string type() const { return "malloc"; }
- };
-
-/**
-* Allocator using malloc plus locking
-*/
-class Locking_Allocator : public Pooling_Allocator
- {
- public:
- /**
- * @param mutex used for internal locking
- */
- Locking_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {}
-
- std::string type() const { return "locking"; }
- private:
- void* alloc_block(size_t);
- void dealloc_block(void*, size_t);
- };
-
-}
-
-#endif
diff --git a/src/alloc/system_alloc/info.txt b/src/alloc/system_alloc/info.txt
deleted file mode 100644
index 87de0cb67..000000000
--- a/src/alloc/system_alloc/info.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-<source>
-defalloc.cpp
-</source>
-
-<header:internal>
-defalloc.h
-</header:internal>
-
-<requires>
-libstate
-mem_pool
-</requires>
diff --git a/src/asn1/alg_id.cpp b/src/asn1/alg_id.cpp
index 665e42fb3..c4c6b6e24 100644
--- a/src/asn1/alg_id.cpp
+++ b/src/asn1/alg_id.cpp
@@ -16,7 +16,7 @@ namespace Botan {
* Create an AlgorithmIdentifier
*/
AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id,
- const MemoryRegion<byte>& param)
+ const std::vector<byte>& param)
{
oid = alg_id;
parameters = param;
@@ -26,7 +26,7 @@ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id,
* Create an AlgorithmIdentifier
*/
AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id,
- const MemoryRegion<byte>& param)
+ const std::vector<byte>& param)
{
oid = OIDS::lookup(alg_id);
parameters = param;
diff --git a/src/asn1/alg_id.h b/src/asn1/alg_id.h
index 417a71b30..1ec6b62d3 100644
--- a/src/asn1/alg_id.h
+++ b/src/asn1/alg_id.h
@@ -29,11 +29,11 @@ class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object
AlgorithmIdentifier(const OID&, Encoding_Option);
AlgorithmIdentifier(const std::string&, Encoding_Option);
- AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&);
- AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&);
+ AlgorithmIdentifier(const OID&, const std::vector<byte>&);
+ AlgorithmIdentifier(const std::string&, const std::vector<byte>&);
OID oid;
- SecureVector<byte> parameters;
+ std::vector<byte> parameters;
};
/*
diff --git a/src/asn1/asn1_alt.cpp b/src/asn1/asn1_alt.cpp
index 2d8e3a1d2..1a5c699cd 100644
--- a/src/asn1/asn1_alt.cpp
+++ b/src/asn1/asn1_alt.cpp
@@ -58,9 +58,8 @@ void AlternativeName::add_attribute(const std::string& type,
if(type == "" || str == "")
return;
- typedef std::multimap<std::string, std::string>::iterator iter;
- std::pair<iter, iter> range = alt_info.equal_range(type);
- for(iter j = range.first; j != range.second; ++j)
+ auto range = alt_info.equal_range(type);
+ for(auto j = range.first; j != range.second; ++j)
if(j->second == str)
return;
@@ -101,13 +100,11 @@ std::multimap<std::string, std::string> AlternativeName::contents() const
{
std::multimap<std::string, std::string> names;
- typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
- for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j)
- multimap_insert(names, j->first, j->second);
+ for(auto i = alt_info.begin(); i != alt_info.end(); ++i)
+ multimap_insert(names, i->first, i->second);
- typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
- for(on_iter j = othernames.begin(); j != othernames.end(); ++j)
- multimap_insert(names, OIDS::lookup(j->first), j->second.value());
+ for(auto i = othernames.begin(); i != othernames.end(); ++i)
+ multimap_insert(names, OIDS::lookup(i->first), i->second.value());
return names;
}
@@ -129,19 +126,18 @@ void encode_entries(DER_Encoder& encoder,
const std::multimap<std::string, std::string>& attr,
const std::string& type, ASN1_Tag tagging)
{
- typedef std::multimap<std::string, std::string>::const_iterator iter;
+ auto range = attr.equal_range(type);
- std::pair<iter, iter> range = attr.equal_range(type);
- for(iter j = range.first; j != range.second; ++j)
+ for(auto i = range.first; i != range.second; ++i)
{
if(type == "RFC822" || type == "DNS" || type == "URI")
{
- ASN1_String asn1_string(j->second, IA5_STRING);
+ ASN1_String asn1_string(i->second, IA5_STRING);
encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859());
}
else if(type == "IP")
{
- const u32bit ip = string_to_ipv4(j->second);
+ const u32bit ip = string_to_ipv4(i->second);
byte ip_buf[4] = { 0 };
store_be(ip, ip_buf);
encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4);
@@ -163,8 +159,7 @@ void AlternativeName::encode_into(DER_Encoder& der) const
encode_entries(der, alt_info, "URI", ASN1_Tag(6));
encode_entries(der, alt_info, "IP", ASN1_Tag(7));
- std::multimap<OID, ASN1_String>::const_iterator i;
- for(i = othernames.begin(); i != othernames.end(); ++i)
+ for(auto i = othernames.begin(); i != othernames.end(); ++i)
{
der.start_explicit(0)
.encode(i->first)
diff --git a/src/asn1/asn1_att.cpp b/src/asn1/asn1_att.cpp
index c8d771e25..c0adae643 100644
--- a/src/asn1/asn1_att.cpp
+++ b/src/asn1/asn1_att.cpp
@@ -15,7 +15,7 @@ namespace Botan {
/*
* Create an Attribute
*/
-Attribute::Attribute(const OID& attr_oid, const MemoryRegion<byte>& attr_value)
+Attribute::Attribute(const OID& attr_oid, const std::vector<byte>& attr_value)
{
oid = attr_oid;
parameters = attr_value;
@@ -25,7 +25,7 @@ Attribute::Attribute(const OID& attr_oid, const MemoryRegion<byte>& attr_value)
* Create an Attribute
*/
Attribute::Attribute(const std::string& attr_oid,
- const MemoryRegion<byte>& attr_value)
+ const std::vector<byte>& attr_value)
{
oid = OIDS::lookup(attr_oid);
parameters = attr_value;
diff --git a/src/asn1/asn1_int.cpp b/src/asn1/asn1_int.cpp
index 75cb1f90c..ff8eba54e 100644
--- a/src/asn1/asn1_int.cpp
+++ b/src/asn1/asn1_int.cpp
@@ -20,24 +20,24 @@ BER_Decoding_Error::BER_Decoding_Error(const std::string& str) :
Decoding_Error("BER: " + str) {}
BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) :
- BER_Decoding_Error(str + ": " + to_string(tag)) {}
+ BER_Decoding_Error(str + ": " + std::to_string(tag)) {}
BER_Bad_Tag::BER_Bad_Tag(const std::string& str,
ASN1_Tag tag1, ASN1_Tag tag2) :
- BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {}
+ BER_Decoding_Error(str + ": " + std::to_string(tag1) + "/" + std::to_string(tag2)) {}
namespace ASN1 {
/*
* Put some arbitrary bytes into a SEQUENCE
*/
-SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& contents)
+std::vector<byte> put_in_sequence(const std::vector<byte>& contents)
{
return DER_Encoder()
.start_cons(SEQUENCE)
.raw_bytes(contents)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
diff --git a/src/asn1/asn1_int.h b/src/asn1/asn1_int.h
index 25b3cf100..37edc4e3c 100644
--- a/src/asn1/asn1_int.h
+++ b/src/asn1/asn1_int.h
@@ -80,7 +80,7 @@ class BOTAN_DLL BER_Object
void assert_is_a(ASN1_Tag, ASN1_Tag);
ASN1_Tag type_tag, class_tag;
- SecureVector<byte> value;
+ secure_vector<byte> value;
};
/*
@@ -90,7 +90,7 @@ class DataSource;
namespace ASN1 {
-SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& val);
+std::vector<byte> put_in_sequence(const std::vector<byte>& val);
std::string to_string(const BER_Object& obj);
/**
diff --git a/src/asn1/asn1_obj.h b/src/asn1/asn1_obj.h
index 692a6fde6..cee5a18ed 100644
--- a/src/asn1/asn1_obj.h
+++ b/src/asn1/asn1_obj.h
@@ -15,6 +15,7 @@
#include <botan/alg_id.h>
#include <vector>
#include <map>
+#include <chrono>
namespace Botan {
@@ -28,11 +29,11 @@ class BOTAN_DLL Attribute : public ASN1_Object
void decode_from(class BER_Decoder& from);
OID oid;
- MemoryVector<byte> parameters;
+ std::vector<byte> parameters;
Attribute() {}
- Attribute(const OID&, const MemoryRegion<byte>&);
- Attribute(const std::string&, const MemoryRegion<byte>&);
+ Attribute(const OID&, const std::vector<byte>&);
+ Attribute(const std::string&, const std::vector<byte>&);
};
/**
@@ -53,7 +54,7 @@ class BOTAN_DLL X509_Time : public ASN1_Object
void set_to(const std::string&);
void set_to(const std::string&, ASN1_Tag);
- X509_Time(u64bit);
+ X509_Time(const std::chrono::system_clock::time_point& time);
X509_Time(const std::string& = "");
X509_Time(const std::string&, ASN1_Tag);
private:
diff --git a/src/asn1/asn1_oid.cpp b/src/asn1/asn1_oid.cpp
index ae3d48ce2..009b1c2fc 100644
--- a/src/asn1/asn1_oid.cpp
+++ b/src/asn1/asn1_oid.cpp
@@ -52,7 +52,7 @@ std::string OID::as_string() const
std::string oid_str;
for(size_t i = 0; i != id.size(); ++i)
{
- oid_str += to_string(id[i]);
+ oid_str += std::to_string(id[i]);
if(i != id.size() - 1)
oid_str += '.';
}
@@ -129,7 +129,7 @@ void OID::encode_into(DER_Encoder& der) const
if(id.size() < 2)
throw Invalid_Argument("OID::encode_into: OID is invalid");
- MemoryVector<byte> encoding;
+ std::vector<byte> encoding;
encoding.push_back(40 * id[0] + id[1]);
for(size_t i = 2; i != id.size(); ++i)
diff --git a/src/asn1/asn1_str.cpp b/src/asn1/asn1_str.cpp
index b28f36d90..44db189f9 100644
--- a/src/asn1/asn1_str.cpp
+++ b/src/asn1/asn1_str.cpp
@@ -77,7 +77,7 @@ ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t)
tag != UTF8_STRING &&
tag != BMP_STRING)
throw Invalid_Argument("ASN1_String: Unknown string type " +
- to_string(tag));
+ std::to_string(tag));
}
/*
diff --git a/src/asn1/asn1_tm.cpp b/src/asn1/asn1_tm.cpp
index a059e0528..b8095a41c 100644
--- a/src/asn1/asn1_tm.cpp
+++ b/src/asn1/asn1_tm.cpp
@@ -10,7 +10,7 @@
#include <botan/ber_dec.h>
#include <botan/charset.h>
#include <botan/parsing.h>
-#include <botan/time.h>
+#include <botan/calendar.h>
namespace Botan {
@@ -23,11 +23,11 @@ X509_Time::X509_Time(const std::string& time_str)
}
/*
-* Create an X509_Time
+* Create a X509_Time from a time point
*/
-X509_Time::X509_Time(u64bit timer)
+X509_Time::X509_Time(const std::chrono::system_clock::time_point& time)
{
- calendar_point cal = calendar_value(timer);
+ calendar_point cal = calendar_value(time);
year = cal.year;
month = cal.month;
@@ -98,7 +98,7 @@ void X509_Time::set_to(const std::string& time_str)
void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag)
{
if(spec_tag != GENERALIZED_TIME && spec_tag != UTC_TIME)
- throw Invalid_Argument("X509_Time: Invalid tag " + to_string(spec_tag));
+ throw Invalid_Argument("X509_Time: Invalid tag " + std::to_string(spec_tag));
if(spec_tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15)
throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec);
@@ -182,24 +182,30 @@ std::string X509_Time::as_string() const
if(time_is_set() == false)
throw Invalid_State("X509_Time::as_string: No time set");
- std::string asn1rep;
- if(tag == GENERALIZED_TIME)
- asn1rep = to_string(year, 4);
- else if(tag == UTC_TIME)
+ u32bit full_year = year;
+
+ if(tag == UTC_TIME)
{
if(year < 1950 || year >= 2050)
throw Encoding_Error("X509_Time: The time " + readable_string() +
" cannot be encoded as a UTCTime");
- u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900);
- asn1rep = to_string(asn1year, 2);
+
+ full_year = (year >= 2000) ? (year - 2000) : (year - 1900);
}
- else
- throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag));
- asn1rep += to_string(month, 2) + to_string(day, 2);
- asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2);
- asn1rep += "Z";
- return asn1rep;
+ std::string repr = std::to_string(full_year*10000000000 +
+ month*100000000 +
+ day*1000000 +
+ hour*10000 +
+ minute*100 +
+ second) + "Z";
+
+ u32bit desired_size = (tag == UTC_TIME) ? 13 : 15;
+
+ while(repr.size() < desired_size)
+ repr = "0" + repr;
+
+ return repr;
}
/*
@@ -218,14 +224,12 @@ std::string X509_Time::readable_string() const
if(time_is_set() == false)
throw Invalid_State("X509_Time::readable_string: No time set");
- std::string readable;
- readable += to_string(year, 4) + "/";
- readable += to_string(month ) + "/";
- readable += to_string(day ) + " ";
- readable += to_string(hour ) + ":";
- readable += to_string(minute, 2) + ":";
- readable += to_string(second, 2) + " UTC";
- return readable;
+ std::string output(24, 0);
+
+ std::sprintf(&output[0], "%04d/%02d/%02d %02d:%02d:%02d UTC",
+ year, month, day, hour, minute, second);
+
+ return output;
}
/*
diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index b31c7b903..dbd59988b 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -99,7 +99,7 @@ size_t decode_length(DataSource* ber)
*/
size_t find_eoc(DataSource* ber)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data;
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE), data;
while(true)
{
@@ -141,7 +141,11 @@ size_t find_eoc(DataSource* ber)
void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag)
{
if(this->type_tag != type_tag || this->class_tag != class_tag)
- throw BER_Decoding_Error("Tag mismatch when decoding");
+ throw BER_Decoding_Error("Tag mismatch when decoding got " +
+ std::to_string(this->type_tag) + "/" +
+ std::to_string(this->class_tag) + " expected " +
+ std::to_string(type_tag) + "/" +
+ std::to_string(class_tag));
}
/*
@@ -167,7 +171,16 @@ BER_Decoder& BER_Decoder::verify_end()
/*
* Save all the bytes remaining in the source
*/
-BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out)
+BER_Decoder& BER_Decoder::raw_bytes(secure_vector<byte>& out)
+ {
+ out.clear();
+ byte buf;
+ while(source->read_byte(buf))
+ out.push_back(buf);
+ return (*this);
+ }
+
+BER_Decoder& BER_Decoder::raw_bytes(std::vector<byte>& out)
{
out.clear();
byte buf;
@@ -208,7 +221,10 @@ BER_Object BER_Decoder::get_next_object()
size_t length = decode_length(source);
next.value.resize(length);
if(source->read(&next.value[0], length) != length)
+ {
+ abort();
throw BER_Decoding_Error("Value truncated");
+ }
if(next.type_tag == EOC && next.class_tag == UNIVERSAL)
return get_next_object();
@@ -260,7 +276,7 @@ BER_Decoder::BER_Decoder(DataSource& src)
source = &src;
owns = false;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
}
/*
@@ -271,18 +287,29 @@ BER_Decoder::BER_Decoder(const byte data[], size_t length)
source = new DataSource_Memory(data, length);
owns = true;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
}
/*
* BER_Decoder Constructor
*/
-BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data)
+BER_Decoder::BER_Decoder(const secure_vector<byte>& data)
{
source = new DataSource_Memory(data);
owns = true;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
+ }
+
+/*
+* BER_Decoder Constructor
+*/
+BER_Decoder::BER_Decoder(const std::vector<byte>& data)
+ {
+ source = new DataSource_Memory(&data[0], data.size());
+ owns = true;
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = nullptr;
}
/*
@@ -308,7 +335,7 @@ BER_Decoder::~BER_Decoder()
{
if(owns)
delete source;
- source = 0;
+ source = nullptr;
}
/*
@@ -358,7 +385,7 @@ BER_Decoder& BER_Decoder::decode(BigInt& out)
BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out)
{
- SecureVector<byte> out_vec;
+ secure_vector<byte> out_vec;
decode(out_vec, OCTET_STRING);
out = BigInt::decode(&out_vec[0], out_vec.size());
return (*this);
@@ -400,6 +427,29 @@ BER_Decoder& BER_Decoder::decode(size_t& out,
}
/*
+* Decode a small BER encoded INTEGER
+*/
+u64bit BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ size_t T_bytes)
+ {
+ if(T_bytes > 8)
+ throw BER_Decoding_Error("Can't decode small integer over 8 bytes");
+
+ BigInt integer;
+ decode(integer, type_tag, class_tag);
+
+ if(integer.bits() > 8*T_bytes)
+ throw BER_Decoding_Error("Decoded integer value larger than expected");
+
+ u64bit out = 0;
+ for(size_t i = 0; i != 8; ++i)
+ out = (out << 8) | integer.byte_at(7-i);
+
+ return out;
+ }
+
+/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out,
@@ -435,7 +485,15 @@ BER_Decoder& BER_Decoder::decode(BigInt& out,
/*
* BER decode a BIT STRING or OCTET STRING
*/
-BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
+BER_Decoder& BER_Decoder::decode(secure_vector<byte>& out, ASN1_Tag real_type)
+ {
+ return decode(out, real_type, real_type, UNIVERSAL);
+ }
+
+/*
+* BER decode a BIT STRING or OCTET STRING
+*/
+BER_Decoder& BER_Decoder::decode(std::vector<byte>& out, ASN1_Tag real_type)
{
return decode(out, real_type, real_type, UNIVERSAL);
}
@@ -443,7 +501,7 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
/*
* BER decode a BIT STRING or OCTET STRING
*/
-BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
+BER_Decoder& BER_Decoder::decode(secure_vector<byte>& buffer,
ASN1_Tag real_type,
ASN1_Tag type_tag, ASN1_Tag class_tag)
{
@@ -466,10 +524,50 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
return (*this);
}
+BER_Decoder& BER_Decoder::decode(std::vector<byte>& buffer,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if(real_type != OCTET_STRING && real_type != BIT_STRING)
+ throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);
+
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(type_tag, class_tag);
+
+ if(real_type == OCTET_STRING)
+ buffer = unlock(obj.value);
+ else
+ {
+ if(obj.value[0] >= 8)
+ throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
+
+ buffer.resize(obj.value.size() - 1);
+ copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1);
+ }
+ return (*this);
+ }
+
/*
* Decode an OPTIONAL string type
*/
-BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out,
+BER_Decoder& BER_Decoder::decode_optional_string(secure_vector<byte>& out,
+ ASN1_Tag real_type,
+ u16bit type_no)
+ {
+ BER_Object obj = get_next_object();
+
+ ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);
+
+ out.clear();
+ push_back(obj);
+
+ if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC)
+ decode(out, real_type, type_tag, CONTEXT_SPECIFIC);
+
+ return (*this);
+ }
+
+BER_Decoder& BER_Decoder::decode_optional_string(std::vector<byte>& out,
ASN1_Tag real_type,
u16bit type_no)
{
diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h
index 5f79d3fc1..6b010fcc4 100644
--- a/src/asn1/ber_dec.h
+++ b/src/asn1/ber_dec.h
@@ -20,33 +20,68 @@ class BOTAN_DLL BER_Decoder
{
public:
BER_Object get_next_object();
- void push_back(const BER_Object&);
+ void push_back(const BER_Object& obj);
bool more_items() const;
BER_Decoder& verify_end();
BER_Decoder& discard_remaining();
- BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
+ BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag = UNIVERSAL);
BER_Decoder& end_cons();
- BER_Decoder& raw_bytes(MemoryRegion<byte>&);
+ BER_Decoder& raw_bytes(secure_vector<byte>& v);
+ BER_Decoder& raw_bytes(std::vector<byte>& v);
BER_Decoder& decode_null();
- BER_Decoder& decode(bool&);
- BER_Decoder& decode(size_t&);
- BER_Decoder& decode(class BigInt&);
- BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag);
+ BER_Decoder& decode(bool& v);
+ BER_Decoder& decode(size_t& v);
+ BER_Decoder& decode(class BigInt& v);
+ BER_Decoder& decode(std::vector<byte>& v, ASN1_Tag type_tag);
+ BER_Decoder& decode(secure_vector<byte>& v, ASN1_Tag type_tag);
- BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
- BER_Decoder& decode(size_t&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
- BER_Decoder& decode(class BigInt&,
- ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
- BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag,
- ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(bool& v,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
- BER_Decoder& decode(class ASN1_Object&);
+ BER_Decoder& decode(size_t& v,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
- BER_Decoder& decode_octet_string_bigint(class BigInt&);
+ BER_Decoder& decode(class BigInt& v,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
+
+ BER_Decoder& decode(std::vector<byte>& v,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
+
+ BER_Decoder& decode(secure_vector<byte>& v,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
+
+ BER_Decoder& decode(class ASN1_Object& obj);
+
+ BER_Decoder& decode_octet_string_bigint(class BigInt& b);
+
+ u64bit decode_constrained_integer(ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ size_t T_bytes);
+
+ template<typename T> BER_Decoder& decode_integer_type(T& out)
+ {
+ return decode_integer_type<T>(out, INTEGER, UNIVERSAL);
+ }
+
+ template<typename T>
+ BER_Decoder& decode_integer_type(T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC)
+ {
+ out = decode_constrained_integer(type_tag, class_tag, sizeof(out));
+ return (*this);
+ }
template<typename T>
BER_Decoder& decode_optional(T& out,
@@ -71,17 +106,27 @@ class BOTAN_DLL BER_Decoder
return (*this);
}
- BER_Decoder& decode_optional_string(MemoryRegion<byte>&,
- ASN1_Tag, u16bit);
+ BER_Decoder& decode_optional_string(std::vector<byte>& out,
+ ASN1_Tag real_type,
+ u16bit type_no);
+
+ BER_Decoder& decode_optional_string(secure_vector<byte>& out,
+ ASN1_Tag real_type,
+ u16bit type_no);
+
+ BER_Decoder& operator=(const BER_Decoder&) = delete;
BER_Decoder(DataSource&);
+
BER_Decoder(const byte[], size_t);
- BER_Decoder(const MemoryRegion<byte>&);
+
+ BER_Decoder(const secure_vector<byte>&);
+
+ BER_Decoder(const std::vector<byte>& vec);
+
BER_Decoder(const BER_Decoder&);
~BER_Decoder();
private:
- BER_Decoder& operator=(const BER_Decoder&) { return (*this); }
-
BER_Decoder* parent;
DataSource* source;
BER_Object pushed;
diff --git a/src/asn1/der_enc.cpp b/src/asn1/der_enc.cpp
index a14b3c5e2..594c32539 100644
--- a/src/asn1/der_enc.cpp
+++ b/src/asn1/der_enc.cpp
@@ -20,13 +20,13 @@ namespace {
/*
* DER encode an ASN.1 type tag
*/
-SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag)
+secure_vector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag)
{
if((class_tag | 0xE0) != 0xE0)
throw Encoding_Error("DER_Encoder: Invalid class tag " +
- to_string(class_tag));
+ std::to_string(class_tag));
- SecureVector<byte> encoded_tag;
+ secure_vector<byte> encoded_tag;
if(type_tag <= 30)
encoded_tag.push_back(static_cast<byte>(type_tag | class_tag));
else
@@ -46,9 +46,9 @@ SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag)
/*
* DER encode an ASN.1 length field
*/
-SecureVector<byte> encode_length(size_t length)
+secure_vector<byte> encode_length(size_t length)
{
- SecureVector<byte> encoded_length;
+ secure_vector<byte> encoded_length;
if(length <= 127)
encoded_length.push_back(static_cast<byte>(length));
else
@@ -68,7 +68,7 @@ SecureVector<byte> encode_length(size_t length)
/*
* Return the encoded SEQUENCE/SET
*/
-SecureVector<byte> DER_Encoder::DER_Sequence::get_contents()
+secure_vector<byte> DER_Encoder::DER_Sequence::get_contents()
{
const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED);
@@ -80,7 +80,7 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents()
set_contents.clear();
}
- SecureVector<byte> result;
+ secure_vector<byte> result;
result += encode_tag(type_tag, real_class_tag);
result += encode_length(contents.size());
result += contents;
@@ -95,7 +95,7 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents()
void DER_Encoder::DER_Sequence::add_bytes(const byte data[], size_t length)
{
if(type_tag == SET)
- set_contents.push_back(SecureVector<byte>(data, length));
+ set_contents.push_back(secure_vector<byte>(data, data + length));
else
contents += std::make_pair(data, length);
}
@@ -119,12 +119,12 @@ DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) :
/*
* Return the encoded contents
*/
-SecureVector<byte> DER_Encoder::get_contents()
+secure_vector<byte> DER_Encoder::get_contents()
{
if(subsequences.size() != 0)
throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
- SecureVector<byte> output;
+ secure_vector<byte> output;
std::swap(output, contents);
return output;
}
@@ -147,7 +147,7 @@ DER_Encoder& DER_Encoder::end_cons()
if(subsequences.empty())
throw Invalid_State("DER_Encoder::end_cons: No such sequence");
- SecureVector<byte> seq = subsequences[subsequences.size()-1].get_contents();
+ secure_vector<byte> seq = subsequences[subsequences.size()-1].get_contents();
subsequences.pop_back();
raw_bytes(seq);
return (*this);
@@ -177,7 +177,12 @@ DER_Encoder& DER_Encoder::end_explicit()
/*
* Write raw bytes into the stream
*/
-DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion<byte>& val)
+DER_Encoder& DER_Encoder::raw_bytes(const secure_vector<byte>& val)
+ {
+ return raw_bytes(&val[0], val.size());
+ }
+
+DER_Encoder& DER_Encoder::raw_bytes(const std::vector<byte>& val)
{
return raw_bytes(&val[0], val.size());
}
@@ -200,7 +205,7 @@ DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], size_t length)
*/
DER_Encoder& DER_Encoder::encode_null()
{
- return add_object(NULL_TAG, UNIVERSAL, 0, 0);
+ return add_object(NULL_TAG, UNIVERSAL, nullptr, 0);
}
/*
@@ -230,7 +235,17 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n)
/*
* DER encode an OCTET STRING or BIT STRING
*/
-DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes,
+DER_Encoder& DER_Encoder::encode(const secure_vector<byte>& bytes,
+ ASN1_Tag real_type)
+ {
+ return encode(&bytes[0], bytes.size(),
+ real_type, real_type, UNIVERSAL);
+ }
+
+/*
+* DER encode an OCTET STRING or BIT STRING
+*/
+DER_Encoder& DER_Encoder::encode(const std::vector<byte>& bytes,
ASN1_Tag real_type)
{
return encode(&bytes[0], bytes.size(),
@@ -275,7 +290,7 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n,
return add_object(type_tag, class_tag, 0);
bool extra_zero = (n.bits() % 8 == 0);
- SecureVector<byte> contents(extra_zero + n.bytes());
+ secure_vector<byte> contents(extra_zero + n.bytes());
BigInt::encode(&contents[extra_zero], n);
if(n < 0)
{
@@ -292,7 +307,18 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n,
/*
* DER encode an OCTET STRING or BIT STRING
*/
-DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes,
+DER_Encoder& DER_Encoder::encode(const secure_vector<byte>& bytes,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ return encode(&bytes[0], bytes.size(),
+ real_type, type_tag, class_tag);
+ }
+
+/*
+* DER encode an OCTET STRING or BIT STRING
+*/
+DER_Encoder& DER_Encoder::encode(const std::vector<byte>& bytes,
ASN1_Tag real_type,
ASN1_Tag type_tag, ASN1_Tag class_tag)
{
@@ -312,7 +338,7 @@ DER_Encoder& DER_Encoder::encode(const byte bytes[], size_t length,
if(real_type == BIT_STRING)
{
- SecureVector<byte> encoded;
+ secure_vector<byte> encoded;
encoded.push_back(0);
encoded += std::make_pair(bytes, length);
return add_object(type_tag, class_tag, encoded);
@@ -346,7 +372,7 @@ DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj)
DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const byte rep[], size_t length)
{
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
buffer += encode_tag(type_tag, class_tag);
buffer += encode_length(length);
buffer += std::make_pair(rep, length);
@@ -358,17 +384,6 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
* Write the encoding of the byte(s)
*/
DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
- const MemoryRegion<byte>& rep_buf)
- {
- const byte* rep = &rep_buf[0];
- const size_t rep_len = rep_buf.size();
- return add_object(type_tag, class_tag, rep, rep_len);
- }
-
-/*
-* Write the encoding of the byte(s)
-*/
-DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const std::string& rep_str)
{
const byte* rep = reinterpret_cast<const byte*>(rep_str.data());
diff --git a/src/asn1/der_enc.h b/src/asn1/der_enc.h
index 183e43b80..adab02247 100644
--- a/src/asn1/der_enc.h
+++ b/src/asn1/der_enc.h
@@ -22,7 +22,10 @@ class ASN1_Object;
class BOTAN_DLL DER_Encoder
{
public:
- SecureVector<byte> get_contents();
+ secure_vector<byte> get_contents();
+
+ std::vector<byte> get_contents_unlocked()
+ { return unlock(get_contents()); }
DER_Encoder& start_cons(ASN1_Tag type_tag,
ASN1_Tag class_tag = UNIVERSAL);
@@ -32,13 +35,15 @@ class BOTAN_DLL DER_Encoder
DER_Encoder& end_explicit();
DER_Encoder& raw_bytes(const byte val[], size_t len);
- DER_Encoder& raw_bytes(const MemoryRegion<byte>& val);
+ DER_Encoder& raw_bytes(const secure_vector<byte>& val);
+ DER_Encoder& raw_bytes(const std::vector<byte>& val);
DER_Encoder& encode_null();
DER_Encoder& encode(bool b);
DER_Encoder& encode(size_t s);
DER_Encoder& encode(const BigInt& n);
- DER_Encoder& encode(const MemoryRegion<byte>& v, ASN1_Tag real_type);
+ DER_Encoder& encode(const secure_vector<byte>& v, ASN1_Tag real_type);
+ DER_Encoder& encode(const std::vector<byte>& v, ASN1_Tag real_type);
DER_Encoder& encode(const byte val[], size_t len, ASN1_Tag real_type);
DER_Encoder& encode(bool b,
@@ -53,7 +58,12 @@ class BOTAN_DLL DER_Encoder
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
- DER_Encoder& encode(const MemoryRegion<byte>& v,
+ DER_Encoder& encode(const std::vector<byte>& v,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag = CONTEXT_SPECIFIC);
+
+ DER_Encoder& encode(const secure_vector<byte>& v,
ASN1_Tag real_type,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
@@ -86,7 +96,16 @@ class BOTAN_DLL DER_Encoder
const byte rep[], size_t length);
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
- const MemoryRegion<byte>& rep);
+ const std::vector<byte>& rep)
+ {
+ return add_object(type_tag, class_tag, &rep[0], rep.size());
+ }
+
+ DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
+ const secure_vector<byte>& rep)
+ {
+ return add_object(type_tag, class_tag, &rep[0], rep.size());
+ }
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const std::string& str);
@@ -99,16 +118,16 @@ class BOTAN_DLL DER_Encoder
{
public:
ASN1_Tag tag_of() const;
- SecureVector<byte> get_contents();
+ secure_vector<byte> get_contents();
void add_bytes(const byte[], size_t);
DER_Sequence(ASN1_Tag, ASN1_Tag);
private:
ASN1_Tag type_tag, class_tag;
- SecureVector<byte> contents;
- std::vector< SecureVector<byte> > set_contents;
+ secure_vector<byte> contents;
+ std::vector< secure_vector<byte> > set_contents;
};
- SecureVector<byte> contents;
+ secure_vector<byte> contents;
std::vector<DER_Sequence> subsequences;
};
diff --git a/src/asn1/x509_dn.cpp b/src/asn1/x509_dn.cpp
index ceb12cee6..c6bc70553 100644
--- a/src/asn1/x509_dn.cpp
+++ b/src/asn1/x509_dn.cpp
@@ -27,9 +27,8 @@ X509_DN::X509_DN()
*/
X509_DN::X509_DN(const std::multimap<OID, std::string>& args)
{
- std::multimap<OID, std::string>::const_iterator j;
- for(j = args.begin(); j != args.end(); ++j)
- add_attribute(j->first, j->second);
+ for(auto i = args.begin(); i != args.end(); ++i)
+ add_attribute(i->first, i->second);
}
/*
@@ -37,9 +36,8 @@ X509_DN::X509_DN(const std::multimap<OID, std::string>& args)
*/
X509_DN::X509_DN(const std::multimap<std::string, std::string>& args)
{
- std::multimap<std::string, std::string>::const_iterator j;
- for(j = args.begin(); j != args.end(); ++j)
- add_attribute(OIDS::lookup(j->first), j->second);
+ for(auto i = args.begin(); i != args.end(); ++i)
+ add_attribute(OIDS::lookup(i->first), i->second);
}
/*
@@ -60,11 +58,9 @@ void X509_DN::add_attribute(const OID& oid, const std::string& str)
if(str == "")
return;
- typedef std::multimap<OID, ASN1_String>::iterator rdn_iter;
-
- std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
- for(rdn_iter j = range.first; j != range.second; ++j)
- if(j->second.value() == str)
+ auto range = dn_info.equal_range(oid);
+ for(auto i = range.first; i != range.second; ++i)
+ if(i->second.value() == str)
return;
multimap_insert(dn_info, oid, ASN1_String(str));
@@ -76,11 +72,9 @@ void X509_DN::add_attribute(const OID& oid, const std::string& str)
*/
std::multimap<OID, std::string> X509_DN::get_attributes() const
{
- typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
-
std::multimap<OID, std::string> retval;
- for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
- multimap_insert(retval, j->first, j->second.value());
+ for(auto i = dn_info.begin(); i != dn_info.end(); ++i)
+ multimap_insert(retval, i->first, i->second.value());
return retval;
}
@@ -89,11 +83,9 @@ std::multimap<OID, std::string> X509_DN::get_attributes() const
*/
std::multimap<std::string, std::string> X509_DN::contents() const
{
- typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
-
std::multimap<std::string, std::string> retval;
- for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
- multimap_insert(retval, OIDS::lookup(j->first), j->second.value());
+ for(auto i = dn_info.begin(); i != dn_info.end(); ++i)
+ multimap_insert(retval, OIDS::lookup(i->first), i->second.value());
return retval;
}
@@ -102,21 +94,20 @@ std::multimap<std::string, std::string> X509_DN::contents() const
*/
std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const
{
- typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
-
const OID oid = OIDS::lookup(deref_info_field(attr));
- std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
+
+ auto range = dn_info.equal_range(oid);
std::vector<std::string> values;
- for(rdn_iter j = range.first; j != range.second; ++j)
- values.push_back(j->second.value());
+ for(auto i = range.first; i != range.second; ++i)
+ values.push_back(i->second.value());
return values;
}
/*
* Return the BER encoded data, if any
*/
-MemoryVector<byte> X509_DN::get_bits() const
+std::vector<byte> X509_DN::get_bits() const
{
return dn_bits;
}
@@ -143,15 +134,13 @@ std::string X509_DN::deref_info_field(const std::string& info)
*/
bool operator==(const X509_DN& dn1, const X509_DN& dn2)
{
- typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
-
- std::multimap<OID, std::string> attr1 = dn1.get_attributes();
- std::multimap<OID, std::string> attr2 = dn2.get_attributes();
+ auto attr1 = dn1.get_attributes();
+ auto attr2 = dn2.get_attributes();
if(attr1.size() != attr2.size()) return false;
- rdn_iter p1 = attr1.begin();
- rdn_iter p2 = attr2.begin();
+ auto p1 = attr1.begin();
+ auto p2 = attr2.begin();
while(true)
{
@@ -181,18 +170,15 @@ bool operator!=(const X509_DN& dn1, const X509_DN& dn2)
*/
bool operator<(const X509_DN& dn1, const X509_DN& dn2)
{
- typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
-
- std::multimap<OID, std::string> attr1 = dn1.get_attributes();
- std::multimap<OID, std::string> attr2 = dn2.get_attributes();
+ auto attr1 = dn1.get_attributes();
+ auto attr2 = dn2.get_attributes();
if(attr1.size() < attr2.size()) return true;
if(attr1.size() > attr2.size()) return false;
- for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1)
+ for(auto p1 = attr1.begin(); p1 != attr1.end(); ++p1)
{
- std::multimap<OID, std::string>::const_iterator p2;
- p2 = attr2.find(p1->first);
+ auto p2 = attr2.find(p1->first);
if(p2 == attr2.end()) return false;
if(p1->second > p2->second) return false;
if(p1->second < p2->second) return true;
@@ -210,8 +196,6 @@ void do_ava(DER_Encoder& encoder,
ASN1_Tag string_type, const std::string& oid_str,
bool must_exist = false)
{
- typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
-
const OID oid = OIDS::lookup(oid_str);
const bool exists = (dn_info.find(oid) != dn_info.end());
@@ -219,14 +203,14 @@ void do_ava(DER_Encoder& encoder,
throw Encoding_Error("X509_DN: No entry for " + oid_str);
if(!exists) return;
- std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
+ auto range = dn_info.equal_range(oid);
- for(rdn_iter j = range.first; j != range.second; ++j)
+ for(auto i = range.first; i != range.second; ++i)
{
encoder.start_cons(SET)
.start_cons(SEQUENCE)
.encode(oid)
- .encode(ASN1_String(j->second, string_type))
+ .encode(ASN1_String(i->second, string_type))
.end_cons()
.end_cons();
}
@@ -239,7 +223,7 @@ void do_ava(DER_Encoder& encoder,
*/
void X509_DN::encode_into(DER_Encoder& der) const
{
- std::multimap<OID, std::string> dn_info = get_attributes();
+ auto dn_info = get_attributes();
der.start_cons(SEQUENCE);
@@ -264,7 +248,7 @@ void X509_DN::encode_into(DER_Encoder& der) const
*/
void X509_DN::decode_from(BER_Decoder& source)
{
- MemoryVector<byte> bits;
+ std::vector<byte> bits;
source.start_cons(SEQUENCE)
.raw_bytes(bits)
diff --git a/src/asn1/x509_dn.h b/src/asn1/x509_dn.h
index de44f8c78..f8dc9e782 100644
--- a/src/asn1/x509_dn.h
+++ b/src/asn1/x509_dn.h
@@ -35,14 +35,14 @@ class BOTAN_DLL X509_DN : public ASN1_Object
static std::string deref_info_field(const std::string&);
- MemoryVector<byte> get_bits() const;
+ std::vector<byte> get_bits() const;
X509_DN();
X509_DN(const std::multimap<OID, std::string>&);
X509_DN(const std::multimap<std::string, std::string>&);
private:
std::multimap<OID, ASN1_String> dn_info;
- MemoryVector<byte> dn_bits;
+ std::vector<byte> dn_bits;
};
bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&);
diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp
index dbccd45c1..a9b84f252 100644
--- a/src/benchmark/benchmark.cpp
+++ b/src/benchmark/benchmark.cpp
@@ -1,6 +1,6 @@
/*
* Runtime benchmarking
-* (C) 2008 Jack Lloyd
+* (C) 2008-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,33 +11,40 @@
#include <botan/stream_cipher.h>
#include <botan/hash.h>
#include <botan/mac.h>
-#include <botan/time.h>
#include <memory>
+#include <vector>
+#include <chrono>
namespace Botan {
namespace {
+typedef std::chrono::high_resolution_clock benchmark_clock;
+
/**
* Benchmark Buffered_Computation (hash or MAC)
*/
std::pair<u64bit, u64bit> bench_buf_comp(Buffered_Computation* buf_comp,
- u64bit nanoseconds_max,
+ std::chrono::nanoseconds max_time,
const byte buf[], size_t buf_len)
{
u64bit reps = 0;
- u64bit nanoseconds_used = 0;
- while(nanoseconds_used < nanoseconds_max)
+ std::chrono::nanoseconds time_used(0);
+
+ while(time_used < max_time)
{
- const u64bit start = get_nanoseconds_clock();
+ auto start = benchmark_clock::now();
buf_comp->update(buf, buf_len);
- nanoseconds_used += get_nanoseconds_clock() - start;
+ time_used += std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_clock::now() - start);
++reps;
}
- return std::make_pair(reps * buf_len, nanoseconds_used);
+ u64bit ns_taken =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count();
+
+ return std::make_pair(reps * buf_len, ns_taken);
}
/**
@@ -45,27 +52,32 @@ std::pair<u64bit, u64bit> bench_buf_comp(Buffered_Computation* buf_comp,
*/
std::pair<u64bit, u64bit>
bench_block_cipher(BlockCipher* block_cipher,
- u64bit nanoseconds_max,
+ std::chrono::nanoseconds max_time,
byte buf[], size_t buf_len)
{
const size_t in_blocks = buf_len / block_cipher->block_size();
u64bit reps = 0;
- u64bit nanoseconds_used = 0;
+
+ std::chrono::nanoseconds time_used(0);
block_cipher->set_key(buf, block_cipher->maximum_keylength());
- while(nanoseconds_used < nanoseconds_max)
+ while(time_used < max_time)
{
- const u64bit start = get_nanoseconds_clock();
+ auto start = benchmark_clock::now();
block_cipher->encrypt_n(buf, buf, in_blocks);
- nanoseconds_used += get_nanoseconds_clock() - start;
+ time_used += std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_clock::now() - start);
+ //time_used += benchmark_clock::now() - start;
++reps;
}
+ u64bit ns_taken =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count();
+
return std::make_pair(reps * in_blocks * block_cipher->block_size(),
- nanoseconds_used);
+ ns_taken);
}
/**
@@ -73,24 +85,28 @@ bench_block_cipher(BlockCipher* block_cipher,
*/
std::pair<u64bit, u64bit>
bench_stream_cipher(StreamCipher* stream_cipher,
- u64bit nanoseconds_max,
+ std::chrono::nanoseconds max_time,
byte buf[], size_t buf_len)
{
u64bit reps = 0;
- u64bit nanoseconds_used = 0;
stream_cipher->set_key(buf, stream_cipher->maximum_keylength());
- while(nanoseconds_used < nanoseconds_max)
+ std::chrono::nanoseconds time_used(0);
+
+ while(time_used < max_time)
{
- const u64bit start = get_nanoseconds_clock();
+ auto start = benchmark_clock::now();
stream_cipher->cipher1(buf, buf_len);
- nanoseconds_used += get_nanoseconds_clock() - start;
+ time_used += benchmark_clock::now() - start;
++reps;
}
- return std::make_pair(reps * buf_len, nanoseconds_used);
+ u64bit ns_taken =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count();
+
+ return std::make_pair(reps * buf_len, ns_taken);
}
/**
@@ -98,10 +114,10 @@ bench_stream_cipher(StreamCipher* stream_cipher,
*/
std::pair<u64bit, u64bit>
bench_hash(HashFunction* hash,
- u64bit nanoseconds_max,
+ std::chrono::nanoseconds max_time,
const byte buf[], size_t buf_len)
{
- return bench_buf_comp(hash, nanoseconds_max, buf, buf_len);
+ return bench_buf_comp(hash, max_time, buf, buf_len);
}
/**
@@ -109,11 +125,11 @@ bench_hash(HashFunction* hash,
*/
std::pair<u64bit, u64bit>
bench_mac(MessageAuthenticationCode* mac,
- u64bit nanoseconds_max,
+ std::chrono::nanoseconds max_time,
const byte buf[], size_t buf_len)
{
mac->set_key(buf, mac->maximum_keylength());
- return bench_buf_comp(mac, nanoseconds_max, buf, buf_len);
+ return bench_buf_comp(mac, max_time, buf, buf_len);
}
}
@@ -122,7 +138,7 @@ std::map<std::string, double>
algorithm_benchmark(const std::string& name,
Algorithm_Factory& af,
RandomNumberGenerator& rng,
- u32bit milliseconds,
+ std::chrono::milliseconds milliseconds,
size_t buf_size)
{
std::vector<std::string> providers = af.providers_of(name);
@@ -131,8 +147,7 @@ algorithm_benchmark(const std::string& name,
if(providers.empty()) // no providers, nothing to do
return all_results;
- const u64bit ns_per_provider =
- (static_cast<u64bit>(milliseconds) * 1000 * 1000) / providers.size();
+ std::chrono::nanoseconds ns_per_provider = milliseconds / providers.size();
std::vector<byte> buf(buf_size * 1024);
rng.randomize(&buf[0], buf.size());
@@ -146,7 +161,7 @@ algorithm_benchmark(const std::string& name,
if(const BlockCipher* proto =
af.prototype_block_cipher(name, provider))
{
- std::auto_ptr<BlockCipher> block_cipher(proto->clone());
+ std::unique_ptr<BlockCipher> block_cipher(proto->clone());
results = bench_block_cipher(block_cipher.get(),
ns_per_provider,
&buf[0], buf.size());
@@ -154,7 +169,7 @@ algorithm_benchmark(const std::string& name,
else if(const StreamCipher* proto =
af.prototype_stream_cipher(name, provider))
{
- std::auto_ptr<StreamCipher> stream_cipher(proto->clone());
+ std::unique_ptr<StreamCipher> stream_cipher(proto->clone());
results = bench_stream_cipher(stream_cipher.get(),
ns_per_provider,
&buf[0], buf.size());
@@ -162,14 +177,14 @@ algorithm_benchmark(const std::string& name,
else if(const HashFunction* proto =
af.prototype_hash_function(name, provider))
{
- std::auto_ptr<HashFunction> hash(proto->clone());
+ std::unique_ptr<HashFunction> hash(proto->clone());
results = bench_hash(hash.get(), ns_per_provider,
&buf[0], buf.size());
}
else if(const MessageAuthenticationCode* proto =
af.prototype_mac(name, provider))
{
- std::auto_ptr<MessageAuthenticationCode> mac(proto->clone());
+ std::unique_ptr<MessageAuthenticationCode> mac(proto->clone());
results = bench_mac(mac.get(), ns_per_provider,
&buf[0], buf.size());
}
diff --git a/src/benchmark/benchmark.h b/src/benchmark/benchmark.h
index c47fdc166..17df85e4e 100644
--- a/src/benchmark/benchmark.h
+++ b/src/benchmark/benchmark.h
@@ -1,6 +1,6 @@
/*
* Runtime benchmarking
-* (C) 2008 Jack Lloyd
+* (C) 2008-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -12,6 +12,7 @@
#include <botan/rng.h>
#include <map>
#include <string>
+#include <chrono>
namespace Botan {
@@ -28,7 +29,7 @@ std::map<std::string, double>
BOTAN_DLL algorithm_benchmark(const std::string& name,
Algorithm_Factory& af,
RandomNumberGenerator& rng,
- u32bit milliseconds,
+ std::chrono::milliseconds milliseconds,
size_t buf_size);
}
diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp
index 5f47762a8..6a706fd24 100644
--- a/src/block/aes/aes.cpp
+++ b/src/block/aes/aes.cpp
@@ -414,8 +414,8 @@ const u32bit TD[1024] = {
*/
void aes_encrypt_n(const byte in[], byte out[],
size_t blocks,
- const MemoryRegion<u32bit>& EK,
- const MemoryRegion<byte>& ME)
+ const secure_vector<u32bit>& EK,
+ const secure_vector<byte>& ME)
{
const size_t BLOCK_SIZE = 16;
@@ -525,8 +525,8 @@ void aes_encrypt_n(const byte in[], byte out[],
* AES Decryption
*/
void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
- const MemoryRegion<u32bit>& DK,
- const MemoryRegion<byte>& MD)
+ const secure_vector<u32bit>& DK,
+ const secure_vector<byte>& MD)
{
const size_t BLOCK_SIZE = 16;
@@ -606,10 +606,10 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
}
void aes_key_schedule(const byte key[], size_t length,
- MemoryRegion<u32bit>& EK,
- MemoryRegion<u32bit>& DK,
- MemoryRegion<byte>& ME,
- MemoryRegion<byte>& MD)
+ secure_vector<u32bit>& EK,
+ secure_vector<u32bit>& DK,
+ secure_vector<byte>& ME,
+ secure_vector<byte>& MD)
{
static const u32bit RC[10] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
@@ -617,7 +617,7 @@ void aes_key_schedule(const byte key[], size_t length,
const size_t rounds = (length / 4) + 6;
- SecureVector<u32bit> XEK(length + 32), XDK(length + 32);
+ secure_vector<u32bit> XEK(length + 32), XDK(length + 32);
const size_t X = length / 4;
for(size_t i = 0; i != X; ++i)
@@ -659,6 +659,9 @@ void aes_key_schedule(const byte key[], size_t length,
TD[SE[get_byte(2, XDK[i])] + 512] ^
TD[SE[get_byte(3, XDK[i])] + 768];
+ ME.resize(16);
+ MD.resize(16);
+
for(size_t i = 0; i != 4; ++i)
{
store_be(XEK[i+4*rounds], &ME[4*i]);
diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h
index a165f83b5..5ddd39b08 100644
--- a/src/block/aes/aes.h
+++ b/src/block/aes/aes.h
@@ -18,8 +18,6 @@ namespace Botan {
class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16>
{
public:
- AES_128() : EK(40), DK(40), ME(16), MD(16) {}
-
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
@@ -30,8 +28,8 @@ class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16>
private:
void key_schedule(const byte key[], size_t length);
- SecureVector<u32bit> EK, DK;
- SecureVector<byte> ME, MD;
+ secure_vector<u32bit> EK, DK;
+ secure_vector<byte> ME, MD;
};
/**
@@ -40,8 +38,6 @@ class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16>
class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24>
{
public:
- AES_192() : EK(48), DK(48), ME(16), MD(16) {}
-
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
@@ -52,8 +48,8 @@ class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24>
private:
void key_schedule(const byte key[], size_t length);
- SecureVector<u32bit> EK, DK;
- SecureVector<byte> ME, MD;
+ secure_vector<u32bit> EK, DK;
+ secure_vector<byte> ME, MD;
};
/**
@@ -62,8 +58,6 @@ class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24>
class BOTAN_DLL AES_256 : public Block_Cipher_Fixed_Params<16, 32>
{
public:
- AES_256() : EK(56), DK(56), ME(16), MD(16) {}
-
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
@@ -74,8 +68,8 @@ class BOTAN_DLL AES_256 : public Block_Cipher_Fixed_Params<16, 32>
private:
void key_schedule(const byte key[], size_t length);
- SecureVector<u32bit> EK, DK;
- SecureVector<byte> ME, MD;
+ secure_vector<u32bit> EK, DK;
+ secure_vector<byte> ME, MD;
};
}
diff --git a/src/block/aes_ni/aes_ni.h b/src/block/aes_ni/aes_ni.h
index ae9e5b3f4..4844b7fe8 100644
--- a/src/block/aes_ni/aes_ni.h
+++ b/src/block/aes_ni/aes_ni.h
@@ -31,7 +31,7 @@ class BOTAN_DLL AES_128_NI : public Block_Cipher_Fixed_Params<16, 16>
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
/**
@@ -53,7 +53,7 @@ class BOTAN_DLL AES_192_NI : public Block_Cipher_Fixed_Params<16, 24>
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
/**
@@ -75,7 +75,7 @@ class BOTAN_DLL AES_256_NI : public Block_Cipher_Fixed_Params<16, 32>
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
}
diff --git a/src/block/aes_ssse3/aes_ssse3.cpp b/src/block/aes_ssse3/aes_ssse3.cpp
index 774ccbabb..648f96d67 100644
--- a/src/block/aes_ssse3/aes_ssse3.cpp
+++ b/src/block/aes_ssse3/aes_ssse3.cpp
@@ -378,6 +378,9 @@ void AES_128_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i key = _mm_loadu_si128(reinterpret_cast<const __m128i*>(keyb));
+ EK.resize(11*4);
+ DK.resize(11*4);
+
__m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
__m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
@@ -445,6 +448,9 @@ void AES_192_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81,
0x1F8391B9, 0xAF9DEEB6);
+ EK.resize(13*4);
+ DK.resize(13*4);
+
__m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
__m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
@@ -544,6 +550,9 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81,
0x1F8391B9, 0xAF9DEEB6);
+ EK.resize(15*4);
+ DK.resize(15*4);
+
__m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
__m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
@@ -568,7 +577,7 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t)
_mm_storeu_si128(EK_mm + i, aes_schedule_mangle(key2, i % 4));
_mm_storeu_si128(DK_mm + (14-i), aes_schedule_mangle_dec(key2, (i+2) % 4));
- key2 = aes_schedule_round(NULL, _mm_shuffle_epi32(key2, 0xFF), k_t);
+ key2 = aes_schedule_round(nullptr, _mm_shuffle_epi32(key2, 0xFF), k_t);
_mm_storeu_si128(EK_mm + i + 1, aes_schedule_mangle(key2, (i - 1) % 4));
_mm_storeu_si128(DK_mm + (13-i), aes_schedule_mangle_dec(key2, (i+1) % 4));
}
diff --git a/src/block/aes_ssse3/aes_ssse3.h b/src/block/aes_ssse3/aes_ssse3.h
index 686b7999f..46bae1450 100644
--- a/src/block/aes_ssse3/aes_ssse3.h
+++ b/src/block/aes_ssse3/aes_ssse3.h
@@ -24,12 +24,10 @@ class BOTAN_DLL AES_128_SSSE3 : public Block_Cipher_Fixed_Params<16, 16>
void clear() { zeroise(EK); zeroise(DK); }
std::string name() const { return "AES-128"; }
BlockCipher* clone() const { return new AES_128_SSSE3; }
-
- AES_128_SSSE3() : EK(44), DK(44) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
/**
@@ -44,12 +42,10 @@ class BOTAN_DLL AES_192_SSSE3 : public Block_Cipher_Fixed_Params<16, 24>
void clear() { zeroise(EK); zeroise(DK); }
std::string name() const { return "AES-192"; }
BlockCipher* clone() const { return new AES_192_SSSE3; }
-
- AES_192_SSSE3() : EK(52), DK(52) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
/**
@@ -64,12 +60,10 @@ class BOTAN_DLL AES_256_SSSE3 : public Block_Cipher_Fixed_Params<16, 32>
void clear() { zeroise(EK); zeroise(DK); }
std::string name() const { return "AES-256"; }
BlockCipher* clone() const { return new AES_256_SSSE3; }
-
- AES_256_SSSE3() : EK(60), DK(60) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
}
diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h
index 8e820fc5a..4a07bb048 100644
--- a/src/block/block_cipher.h
+++ b/src/block/block_cipher.h
@@ -75,6 +75,50 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
/**
* Encrypt one or more blocks
+ * @param block the input/output buffer (multiple of block_size())
+ */
+ template<typename Alloc>
+ void encrypt(std::vector<byte, Alloc>& block) const
+ {
+ return encrypt_n(&block[0], &block[0], block.size() / block_size());
+ }
+
+ /**
+ * Decrypt one or more blocks
+ * @param block the input/output buffer (multiple of block_size())
+ */
+ template<typename Alloc>
+ void decrypt(std::vector<byte, Alloc>& block) const
+ {
+ return decrypt_n(&block[0], &block[0], block.size() / block_size());
+ }
+
+ /**
+ * Encrypt one or more blocks
+ * @param in the input buffer (multiple of block_size())
+ * @param out the output buffer (same size as in)
+ */
+ template<typename Alloc, typename Alloc2>
+ void encrypt(const std::vector<byte, Alloc>& in,
+ std::vector<byte, Alloc2>& out) const
+ {
+ return encrypt_n(&in[0], &out[0], in.size() / block_size());
+ }
+
+ /**
+ * Decrypt one or more blocks
+ * @param in the input buffer (multiple of block_size())
+ * @param out the output buffer (same size as in)
+ */
+ template<typename Alloc, typename Alloc2>
+ void decrypt(const std::vector<byte, Alloc>& in,
+ std::vector<byte, Alloc2>& out) const
+ {
+ return decrypt_n(&in[0], &out[0], in.size() / block_size());
+ }
+
+ /**
+ * Encrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
* @param blocks the number of blocks to process
diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp
index b6319eec0..c224f479b 100644
--- a/src/block/blowfish/blowfish.cpp
+++ b/src/block/blowfish/blowfish.cpp
@@ -85,7 +85,11 @@ void Blowfish::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Blowfish::key_schedule(const byte key[], size_t length)
{
- clear();
+ P.resize(18);
+ std::copy(P_INIT, P_INIT + 18, P.begin());
+
+ S.resize(1024);
+ std::copy(S_INIT, S_INIT + 1024, S.begin());
const byte null_salt[16] = { 0 };
@@ -125,12 +129,15 @@ void Blowfish::eks_key_schedule(const byte key[], size_t length,
if(workfactor > 18)
throw std::invalid_argument("Requested Bcrypt work factor too large");
- clear();
+ P.resize(18);
+ std::copy(P_INIT, P_INIT + 18, P.begin());
- const byte null_salt[16] = { 0 };
+ S.resize(1024);
+ std::copy(S_INIT, S_INIT + 1024, S.begin());
key_expansion(key, length, salt);
+ const byte null_salt[16] = { 0 };
const size_t rounds = 1 << workfactor;
for(size_t r = 0; r != rounds; ++r)
@@ -143,7 +150,7 @@ void Blowfish::eks_key_schedule(const byte key[], size_t length,
/*
* Generate one of the Sboxes
*/
-void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
+void Blowfish::generate_sbox(secure_vector<u32bit>& box,
u32bit& L, u32bit& R,
const byte salt[16],
size_t salt_off) const
@@ -180,8 +187,8 @@ void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
*/
void Blowfish::clear()
{
- std::copy(P_INIT, P_INIT + 18, P.begin());
- std::copy(S_INIT, S_INIT + 1024, S.begin());
+ P.clear();
+ S.clear();
}
}
diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h
index 13706d21e..cdf65f285 100644
--- a/src/block/blowfish/blowfish.h
+++ b/src/block/blowfish/blowfish.h
@@ -30,8 +30,6 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
void clear();
std::string name() const { return "Blowfish"; }
BlockCipher* clone() const { return new Blowfish; }
-
- Blowfish() : S(1024), P(18) {}
private:
void key_schedule(const byte key[], size_t length);
@@ -39,7 +37,7 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
size_t key_length,
const byte salt[16]);
- void generate_sbox(MemoryRegion<u32bit>& box,
+ void generate_sbox(secure_vector<u32bit>& box,
u32bit& L, u32bit& R,
const byte salt[16],
size_t salt_off) const;
@@ -47,8 +45,7 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
static const u32bit P_INIT[18];
static const u32bit S_INIT[1024];
- SecureVector<u32bit> S;
- SecureVector<u32bit> P;
+ secure_vector<u32bit> S, P;
};
}
diff --git a/src/block/camellia/camellia.cpp b/src/block/camellia/camellia.cpp
index 054558c35..bea5d4c51 100644
--- a/src/block/camellia/camellia.cpp
+++ b/src/block/camellia/camellia.cpp
@@ -6,13 +6,20 @@
*/
#include <botan/camellia.h>
+#include <botan/internal/camellia_sbox.h>
#include <botan/loadstor.h>
namespace Botan {
namespace Camellia_F {
-u64bit F(u64bit v, u64bit K)
+namespace {
+
+/*
+* We use the slow byte-wise version of F in the first and last rounds
+* to help protect against timing attacks
+*/
+u64bit F_SLOW(u64bit v, u64bit K)
{
static const byte SBOX[256] = {
0x70, 0x82, 0x2C, 0xEC, 0xB3, 0x27, 0xC0, 0xE5, 0xE4, 0x85, 0x57,
@@ -63,7 +70,21 @@ u64bit F(u64bit v, u64bit K)
return make_u64bit(y1, y2, y3, y4, y5, y6, y7, y8);
}
-u64bit FL(u64bit v, u64bit K)
+inline u64bit F(u64bit v, u64bit K)
+ {
+ const u64bit x = v ^ K;
+
+ return Camellia_SBOX1[get_byte(0, x)] ^
+ Camellia_SBOX2[get_byte(1, x)] ^
+ Camellia_SBOX3[get_byte(2, x)] ^
+ Camellia_SBOX4[get_byte(3, x)] ^
+ Camellia_SBOX5[get_byte(4, x)] ^
+ Camellia_SBOX6[get_byte(5, x)] ^
+ Camellia_SBOX7[get_byte(6, x)] ^
+ Camellia_SBOX8[get_byte(7, x)];
+ }
+
+inline u64bit FL(u64bit v, u64bit K)
{
u32bit x1 = (v >> 32);
u32bit x2 = (v & 0xFFFFFFFF);
@@ -77,7 +98,7 @@ u64bit FL(u64bit v, u64bit K)
return ((static_cast<u64bit>(x1) << 32) | x2);
}
-u64bit FLINV(u64bit v, u64bit K)
+inline u64bit FLINV(u64bit v, u64bit K)
{
u32bit x1 = (v >> 32);
u32bit x2 = (v & 0xFFFFFFFF);
@@ -91,25 +112,12 @@ u64bit FLINV(u64bit v, u64bit K)
return ((static_cast<u64bit>(x1) << 32) | x2);
}
-u64bit left_rot_hi(u64bit h, u64bit l, size_t shift)
- {
- return (h << shift) | ((l >> (64-shift)));
- }
-
-u64bit left_rot_lo(u64bit h, u64bit l, size_t shift)
- {
- return (h >> (64-shift)) | (l << shift);
- }
-
-}
-
/*
* Camellia Encryption
*/
-void Camellia::encrypt_n(const byte in[], byte out[], size_t blocks) const
+void encrypt(const byte in[], byte out[], size_t blocks,
+ const secure_vector<u64bit>& SK, const size_t rounds)
{
- using namespace Camellia_F;
-
for(size_t i = 0; i != blocks; ++i)
{
u64bit D1 = load_be<u64bit>(in, 0);
@@ -120,39 +128,40 @@ void Camellia::encrypt_n(const byte in[], byte out[], size_t blocks) const
D1 ^= *K++;
D2 ^= *K++;
- while(true)
+ D2 ^= F_SLOW(D1, *K++);
+ D1 ^= F_SLOW(D2, *K++);
+
+ for(size_t r = 1; r != rounds - 1; ++r)
{
+ if(r % 3 == 0)
+ {
+ D1 = FL (D1, *K++);
+ D2 = FLINV(D2, *K++);
+ }
+
D2 ^= F(D1, *K++);
D1 ^= F(D2, *K++);
- D2 ^= F(D1, *K++);
- D1 ^= F(D2, *K++);
- D2 ^= F(D1, *K++);
- D1 ^= F(D2, *K++);
-
- if(K == &SK[SK.size()-2])
- break;
-
- D1 = FL (D1, *K++);
- D2 = FLINV(D2, *K++);
}
+ D2 ^= F_SLOW(D1, *K++);
+ D1 ^= F_SLOW(D2, *K++);
+
D2 ^= *K++;
D1 ^= *K++;
store_be(out, D2, D1);
- in += BLOCK_SIZE;
- out += BLOCK_SIZE;
+ in += 16;
+ out += 16;
}
}
/*
* Camellia Decryption
*/
-void Camellia::decrypt_n(const byte in[], byte out[], size_t blocks) const
+void decrypt(const byte in[], byte out[], size_t blocks,
+ const secure_vector<u64bit>& SK, const size_t rounds)
{
- using namespace Camellia_F;
-
for(size_t i = 0; i != blocks; ++i)
{
u64bit D1 = load_be<u64bit>(in, 0);
@@ -163,39 +172,49 @@ void Camellia::decrypt_n(const byte in[], byte out[], size_t blocks) const
D2 ^= *K--;
D1 ^= *K--;
- while(true)
+ D2 ^= F_SLOW(D1, *K--);
+ D1 ^= F_SLOW(D2, *K--);
+
+ for(size_t r = 1; r != rounds - 1; ++r)
{
+ if(r % 3 == 0)
+ {
+ D1 = FL (D1, *K--);
+ D2 = FLINV(D2, *K--);
+ }
+
D2 ^= F(D1, *K--);
D1 ^= F(D2, *K--);
- D2 ^= F(D1, *K--);
- D1 ^= F(D2, *K--);
- D2 ^= F(D1, *K--);
- D1 ^= F(D2, *K--);
-
- if(K == &SK[1])
- break;
-
- D1 = FL (D1, *K--);
- D2 = FLINV(D2, *K--);
}
+ D2 ^= F_SLOW(D1, *K--);
+ D1 ^= F_SLOW(D2, *K--);
+
D1 ^= *K--;
D2 ^= *K;
store_be(out, D2, D1);
- in += BLOCK_SIZE;
- out += BLOCK_SIZE;
+ in += 16;
+ out += 16;
}
}
+u64bit left_rot_hi(u64bit h, u64bit l, size_t shift)
+ {
+ return (h << shift) | ((l >> (64-shift)));
+ }
+
+u64bit left_rot_lo(u64bit h, u64bit l, size_t shift)
+ {
+ return (h >> (64-shift)) | (l << shift);
+ }
+
/*
* Camellia Key Schedule
*/
-void Camellia::key_schedule(const byte key[], size_t length)
+void key_schedule(secure_vector<u64bit>& SK, const byte key[], size_t length)
{
- using namespace Camellia_F;
-
const u64bit Sigma1 = 0xA09E667F3BCC908B;
const u64bit Sigma2 = 0xB67AE8584CAA73B2;
const u64bit Sigma3 = 0xC6EF372FE94F82BE;
@@ -309,3 +328,52 @@ void Camellia::key_schedule(const byte key[], size_t length)
}
}
+
+}
+
+void Camellia_128::encrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::encrypt(in, out, blocks, SK, 9);
+ }
+
+void Camellia_192::encrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::encrypt(in, out, blocks, SK, 12);
+ }
+
+void Camellia_256::encrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::encrypt(in, out, blocks, SK, 12);
+ }
+
+void Camellia_128::decrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::decrypt(in, out, blocks, SK, 9);
+ }
+
+void Camellia_192::decrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::decrypt(in, out, blocks, SK, 12);
+ }
+
+void Camellia_256::decrypt_n(const byte in[], byte out[], size_t blocks) const
+ {
+ Camellia_F::decrypt(in, out, blocks, SK, 12);
+ }
+
+void Camellia_128::key_schedule(const byte key[], size_t length)
+ {
+ Camellia_F::key_schedule(SK, key, length);
+ }
+
+void Camellia_192::key_schedule(const byte key[], size_t length)
+ {
+ Camellia_F::key_schedule(SK, key, length);
+ }
+
+void Camellia_256::key_schedule(const byte key[], size_t length)
+ {
+ Camellia_F::key_schedule(SK, key, length);
+ }
+
+}
diff --git a/src/block/camellia/camellia.h b/src/block/camellia/camellia.h
index aaf3ad9e3..4db115f2c 100644
--- a/src/block/camellia/camellia.h
+++ b/src/block/camellia/camellia.h
@@ -13,21 +13,57 @@
namespace Botan {
/**
-* Camellia
+* Camellia-128
+*/
+class BOTAN_DLL Camellia_128 : public Block_Cipher_Fixed_Params<16, 16>
+ {
+ 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;
+
+ void clear() { SK.clear(); }
+ std::string name() const { return "Camellia-128"; }
+ BlockCipher* clone() const { return new Camellia_128; }
+ private:
+ void key_schedule(const byte key[], size_t length);
+
+ secure_vector<u64bit> SK;
+ };
+
+/**
+* Camellia-192
+*/
+class BOTAN_DLL Camellia_192 : public Block_Cipher_Fixed_Params<16, 24>
+ {
+ 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;
+
+ void clear() { SK.clear(); }
+ std::string name() const { return "Camellia-192"; }
+ BlockCipher* clone() const { return new Camellia_192; }
+ private:
+ void key_schedule(const byte key[], size_t length);
+
+ secure_vector<u64bit> SK;
+ };
+
+/**
+* Camellia-256
*/
-class BOTAN_DLL Camellia : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
+class BOTAN_DLL Camellia_256 : public Block_Cipher_Fixed_Params<16, 32>
{
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;
void clear() { SK.clear(); }
- std::string name() const { return "Camellia"; }
- BlockCipher* clone() const { return new Camellia; }
+ std::string name() const { return "Camellia-256"; }
+ BlockCipher* clone() const { return new Camellia_256; }
private:
void key_schedule(const byte key[], size_t length);
- SecureVector<u64bit> SK;
+ secure_vector<u64bit> SK;
};
}
diff --git a/src/block/camellia/camellia_sbox.h b/src/block/camellia/camellia_sbox.h
new file mode 100644
index 000000000..24c849a16
--- /dev/null
+++ b/src/block/camellia/camellia_sbox.h
@@ -0,0 +1,545 @@
+/*
+* Camellia SBox Tables
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CAMELLIA_SBOX_H__
+#define BOTAN_CAMELLIA_SBOX_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+const u64bit Camellia_SBOX1[256] = {
+0x7070700070000070, 0x8282820082000082, 0x2C2C2C002C00002C, 0xECECEC00EC0000EC,
+0xB3B3B300B30000B3, 0x2727270027000027, 0xC0C0C000C00000C0, 0xE5E5E500E50000E5,
+0xE4E4E400E40000E4, 0x8585850085000085, 0x5757570057000057, 0x3535350035000035,
+0xEAEAEA00EA0000EA, 0x0C0C0C000C00000C, 0xAEAEAE00AE0000AE, 0x4141410041000041,
+0x2323230023000023, 0xEFEFEF00EF0000EF, 0x6B6B6B006B00006B, 0x9393930093000093,
+0x4545450045000045, 0x1919190019000019, 0xA5A5A500A50000A5, 0x2121210021000021,
+0xEDEDED00ED0000ED, 0x0E0E0E000E00000E, 0x4F4F4F004F00004F, 0x4E4E4E004E00004E,
+0x1D1D1D001D00001D, 0x6565650065000065, 0x9292920092000092, 0xBDBDBD00BD0000BD,
+0x8686860086000086, 0xB8B8B800B80000B8, 0xAFAFAF00AF0000AF, 0x8F8F8F008F00008F,
+0x7C7C7C007C00007C, 0xEBEBEB00EB0000EB, 0x1F1F1F001F00001F, 0xCECECE00CE0000CE,
+0x3E3E3E003E00003E, 0x3030300030000030, 0xDCDCDC00DC0000DC, 0x5F5F5F005F00005F,
+0x5E5E5E005E00005E, 0xC5C5C500C50000C5, 0x0B0B0B000B00000B, 0x1A1A1A001A00001A,
+0xA6A6A600A60000A6, 0xE1E1E100E10000E1, 0x3939390039000039, 0xCACACA00CA0000CA,
+0xD5D5D500D50000D5, 0x4747470047000047, 0x5D5D5D005D00005D, 0x3D3D3D003D00003D,
+0xD9D9D900D90000D9, 0x0101010001000001, 0x5A5A5A005A00005A, 0xD6D6D600D60000D6,
+0x5151510051000051, 0x5656560056000056, 0x6C6C6C006C00006C, 0x4D4D4D004D00004D,
+0x8B8B8B008B00008B, 0x0D0D0D000D00000D, 0x9A9A9A009A00009A, 0x6666660066000066,
+0xFBFBFB00FB0000FB, 0xCCCCCC00CC0000CC, 0xB0B0B000B00000B0, 0x2D2D2D002D00002D,
+0x7474740074000074, 0x1212120012000012, 0x2B2B2B002B00002B, 0x2020200020000020,
+0xF0F0F000F00000F0, 0xB1B1B100B10000B1, 0x8484840084000084, 0x9999990099000099,
+0xDFDFDF00DF0000DF, 0x4C4C4C004C00004C, 0xCBCBCB00CB0000CB, 0xC2C2C200C20000C2,
+0x3434340034000034, 0x7E7E7E007E00007E, 0x7676760076000076, 0x0505050005000005,
+0x6D6D6D006D00006D, 0xB7B7B700B70000B7, 0xA9A9A900A90000A9, 0x3131310031000031,
+0xD1D1D100D10000D1, 0x1717170017000017, 0x0404040004000004, 0xD7D7D700D70000D7,
+0x1414140014000014, 0x5858580058000058, 0x3A3A3A003A00003A, 0x6161610061000061,
+0xDEDEDE00DE0000DE, 0x1B1B1B001B00001B, 0x1111110011000011, 0x1C1C1C001C00001C,
+0x3232320032000032, 0x0F0F0F000F00000F, 0x9C9C9C009C00009C, 0x1616160016000016,
+0x5353530053000053, 0x1818180018000018, 0xF2F2F200F20000F2, 0x2222220022000022,
+0xFEFEFE00FE0000FE, 0x4444440044000044, 0xCFCFCF00CF0000CF, 0xB2B2B200B20000B2,
+0xC3C3C300C30000C3, 0xB5B5B500B50000B5, 0x7A7A7A007A00007A, 0x9191910091000091,
+0x2424240024000024, 0x0808080008000008, 0xE8E8E800E80000E8, 0xA8A8A800A80000A8,
+0x6060600060000060, 0xFCFCFC00FC0000FC, 0x6969690069000069, 0x5050500050000050,
+0xAAAAAA00AA0000AA, 0xD0D0D000D00000D0, 0xA0A0A000A00000A0, 0x7D7D7D007D00007D,
+0xA1A1A100A10000A1, 0x8989890089000089, 0x6262620062000062, 0x9797970097000097,
+0x5454540054000054, 0x5B5B5B005B00005B, 0x1E1E1E001E00001E, 0x9595950095000095,
+0xE0E0E000E00000E0, 0xFFFFFF00FF0000FF, 0x6464640064000064, 0xD2D2D200D20000D2,
+0x1010100010000010, 0xC4C4C400C40000C4, 0x0000000000000000, 0x4848480048000048,
+0xA3A3A300A30000A3, 0xF7F7F700F70000F7, 0x7575750075000075, 0xDBDBDB00DB0000DB,
+0x8A8A8A008A00008A, 0x0303030003000003, 0xE6E6E600E60000E6, 0xDADADA00DA0000DA,
+0x0909090009000009, 0x3F3F3F003F00003F, 0xDDDDDD00DD0000DD, 0x9494940094000094,
+0x8787870087000087, 0x5C5C5C005C00005C, 0x8383830083000083, 0x0202020002000002,
+0xCDCDCD00CD0000CD, 0x4A4A4A004A00004A, 0x9090900090000090, 0x3333330033000033,
+0x7373730073000073, 0x6767670067000067, 0xF6F6F600F60000F6, 0xF3F3F300F30000F3,
+0x9D9D9D009D00009D, 0x7F7F7F007F00007F, 0xBFBFBF00BF0000BF, 0xE2E2E200E20000E2,
+0x5252520052000052, 0x9B9B9B009B00009B, 0xD8D8D800D80000D8, 0x2626260026000026,
+0xC8C8C800C80000C8, 0x3737370037000037, 0xC6C6C600C60000C6, 0x3B3B3B003B00003B,
+0x8181810081000081, 0x9696960096000096, 0x6F6F6F006F00006F, 0x4B4B4B004B00004B,
+0x1313130013000013, 0xBEBEBE00BE0000BE, 0x6363630063000063, 0x2E2E2E002E00002E,
+0xE9E9E900E90000E9, 0x7979790079000079, 0xA7A7A700A70000A7, 0x8C8C8C008C00008C,
+0x9F9F9F009F00009F, 0x6E6E6E006E00006E, 0xBCBCBC00BC0000BC, 0x8E8E8E008E00008E,
+0x2929290029000029, 0xF5F5F500F50000F5, 0xF9F9F900F90000F9, 0xB6B6B600B60000B6,
+0x2F2F2F002F00002F, 0xFDFDFD00FD0000FD, 0xB4B4B400B40000B4, 0x5959590059000059,
+0x7878780078000078, 0x9898980098000098, 0x0606060006000006, 0x6A6A6A006A00006A,
+0xE7E7E700E70000E7, 0x4646460046000046, 0x7171710071000071, 0xBABABA00BA0000BA,
+0xD4D4D400D40000D4, 0x2525250025000025, 0xABABAB00AB0000AB, 0x4242420042000042,
+0x8888880088000088, 0xA2A2A200A20000A2, 0x8D8D8D008D00008D, 0xFAFAFA00FA0000FA,
+0x7272720072000072, 0x0707070007000007, 0xB9B9B900B90000B9, 0x5555550055000055,
+0xF8F8F800F80000F8, 0xEEEEEE00EE0000EE, 0xACACAC00AC0000AC, 0x0A0A0A000A00000A,
+0x3636360036000036, 0x4949490049000049, 0x2A2A2A002A00002A, 0x6868680068000068,
+0x3C3C3C003C00003C, 0x3838380038000038, 0xF1F1F100F10000F1, 0xA4A4A400A40000A4,
+0x4040400040000040, 0x2828280028000028, 0xD3D3D300D30000D3, 0x7B7B7B007B00007B,
+0xBBBBBB00BB0000BB, 0xC9C9C900C90000C9, 0x4343430043000043, 0xC1C1C100C10000C1,
+0x1515150015000015, 0xE3E3E300E30000E3, 0xADADAD00AD0000AD, 0xF4F4F400F40000F4,
+0x7777770077000077, 0xC7C7C700C70000C7, 0x8080800080000080, 0x9E9E9E009E00009E };
+
+const u64bit Camellia_SBOX2[256] = {
+0x00E0E0E0E0E00000, 0x0005050505050000, 0x0058585858580000, 0x00D9D9D9D9D90000,
+0x0067676767670000, 0x004E4E4E4E4E0000, 0x0081818181810000, 0x00CBCBCBCBCB0000,
+0x00C9C9C9C9C90000, 0x000B0B0B0B0B0000, 0x00AEAEAEAEAE0000, 0x006A6A6A6A6A0000,
+0x00D5D5D5D5D50000, 0x0018181818180000, 0x005D5D5D5D5D0000, 0x0082828282820000,
+0x0046464646460000, 0x00DFDFDFDFDF0000, 0x00D6D6D6D6D60000, 0x0027272727270000,
+0x008A8A8A8A8A0000, 0x0032323232320000, 0x004B4B4B4B4B0000, 0x0042424242420000,
+0x00DBDBDBDBDB0000, 0x001C1C1C1C1C0000, 0x009E9E9E9E9E0000, 0x009C9C9C9C9C0000,
+0x003A3A3A3A3A0000, 0x00CACACACACA0000, 0x0025252525250000, 0x007B7B7B7B7B0000,
+0x000D0D0D0D0D0000, 0x0071717171710000, 0x005F5F5F5F5F0000, 0x001F1F1F1F1F0000,
+0x00F8F8F8F8F80000, 0x00D7D7D7D7D70000, 0x003E3E3E3E3E0000, 0x009D9D9D9D9D0000,
+0x007C7C7C7C7C0000, 0x0060606060600000, 0x00B9B9B9B9B90000, 0x00BEBEBEBEBE0000,
+0x00BCBCBCBCBC0000, 0x008B8B8B8B8B0000, 0x0016161616160000, 0x0034343434340000,
+0x004D4D4D4D4D0000, 0x00C3C3C3C3C30000, 0x0072727272720000, 0x0095959595950000,
+0x00ABABABABAB0000, 0x008E8E8E8E8E0000, 0x00BABABABABA0000, 0x007A7A7A7A7A0000,
+0x00B3B3B3B3B30000, 0x0002020202020000, 0x00B4B4B4B4B40000, 0x00ADADADADAD0000,
+0x00A2A2A2A2A20000, 0x00ACACACACAC0000, 0x00D8D8D8D8D80000, 0x009A9A9A9A9A0000,
+0x0017171717170000, 0x001A1A1A1A1A0000, 0x0035353535350000, 0x00CCCCCCCCCC0000,
+0x00F7F7F7F7F70000, 0x0099999999990000, 0x0061616161610000, 0x005A5A5A5A5A0000,
+0x00E8E8E8E8E80000, 0x0024242424240000, 0x0056565656560000, 0x0040404040400000,
+0x00E1E1E1E1E10000, 0x0063636363630000, 0x0009090909090000, 0x0033333333330000,
+0x00BFBFBFBFBF0000, 0x0098989898980000, 0x0097979797970000, 0x0085858585850000,
+0x0068686868680000, 0x00FCFCFCFCFC0000, 0x00ECECECECEC0000, 0x000A0A0A0A0A0000,
+0x00DADADADADA0000, 0x006F6F6F6F6F0000, 0x0053535353530000, 0x0062626262620000,
+0x00A3A3A3A3A30000, 0x002E2E2E2E2E0000, 0x0008080808080000, 0x00AFAFAFAFAF0000,
+0x0028282828280000, 0x00B0B0B0B0B00000, 0x0074747474740000, 0x00C2C2C2C2C20000,
+0x00BDBDBDBDBD0000, 0x0036363636360000, 0x0022222222220000, 0x0038383838380000,
+0x0064646464640000, 0x001E1E1E1E1E0000, 0x0039393939390000, 0x002C2C2C2C2C0000,
+0x00A6A6A6A6A60000, 0x0030303030300000, 0x00E5E5E5E5E50000, 0x0044444444440000,
+0x00FDFDFDFDFD0000, 0x0088888888880000, 0x009F9F9F9F9F0000, 0x0065656565650000,
+0x0087878787870000, 0x006B6B6B6B6B0000, 0x00F4F4F4F4F40000, 0x0023232323230000,
+0x0048484848480000, 0x0010101010100000, 0x00D1D1D1D1D10000, 0x0051515151510000,
+0x00C0C0C0C0C00000, 0x00F9F9F9F9F90000, 0x00D2D2D2D2D20000, 0x00A0A0A0A0A00000,
+0x0055555555550000, 0x00A1A1A1A1A10000, 0x0041414141410000, 0x00FAFAFAFAFA0000,
+0x0043434343430000, 0x0013131313130000, 0x00C4C4C4C4C40000, 0x002F2F2F2F2F0000,
+0x00A8A8A8A8A80000, 0x00B6B6B6B6B60000, 0x003C3C3C3C3C0000, 0x002B2B2B2B2B0000,
+0x00C1C1C1C1C10000, 0x00FFFFFFFFFF0000, 0x00C8C8C8C8C80000, 0x00A5A5A5A5A50000,
+0x0020202020200000, 0x0089898989890000, 0x0000000000000000, 0x0090909090900000,
+0x0047474747470000, 0x00EFEFEFEFEF0000, 0x00EAEAEAEAEA0000, 0x00B7B7B7B7B70000,
+0x0015151515150000, 0x0006060606060000, 0x00CDCDCDCDCD0000, 0x00B5B5B5B5B50000,
+0x0012121212120000, 0x007E7E7E7E7E0000, 0x00BBBBBBBBBB0000, 0x0029292929290000,
+0x000F0F0F0F0F0000, 0x00B8B8B8B8B80000, 0x0007070707070000, 0x0004040404040000,
+0x009B9B9B9B9B0000, 0x0094949494940000, 0x0021212121210000, 0x0066666666660000,
+0x00E6E6E6E6E60000, 0x00CECECECECE0000, 0x00EDEDEDEDED0000, 0x00E7E7E7E7E70000,
+0x003B3B3B3B3B0000, 0x00FEFEFEFEFE0000, 0x007F7F7F7F7F0000, 0x00C5C5C5C5C50000,
+0x00A4A4A4A4A40000, 0x0037373737370000, 0x00B1B1B1B1B10000, 0x004C4C4C4C4C0000,
+0x0091919191910000, 0x006E6E6E6E6E0000, 0x008D8D8D8D8D0000, 0x0076767676760000,
+0x0003030303030000, 0x002D2D2D2D2D0000, 0x00DEDEDEDEDE0000, 0x0096969696960000,
+0x0026262626260000, 0x007D7D7D7D7D0000, 0x00C6C6C6C6C60000, 0x005C5C5C5C5C0000,
+0x00D3D3D3D3D30000, 0x00F2F2F2F2F20000, 0x004F4F4F4F4F0000, 0x0019191919190000,
+0x003F3F3F3F3F0000, 0x00DCDCDCDCDC0000, 0x0079797979790000, 0x001D1D1D1D1D0000,
+0x0052525252520000, 0x00EBEBEBEBEB0000, 0x00F3F3F3F3F30000, 0x006D6D6D6D6D0000,
+0x005E5E5E5E5E0000, 0x00FBFBFBFBFB0000, 0x0069696969690000, 0x00B2B2B2B2B20000,
+0x00F0F0F0F0F00000, 0x0031313131310000, 0x000C0C0C0C0C0000, 0x00D4D4D4D4D40000,
+0x00CFCFCFCFCF0000, 0x008C8C8C8C8C0000, 0x00E2E2E2E2E20000, 0x0075757575750000,
+0x00A9A9A9A9A90000, 0x004A4A4A4A4A0000, 0x0057575757570000, 0x0084848484840000,
+0x0011111111110000, 0x0045454545450000, 0x001B1B1B1B1B0000, 0x00F5F5F5F5F50000,
+0x00E4E4E4E4E40000, 0x000E0E0E0E0E0000, 0x0073737373730000, 0x00AAAAAAAAAA0000,
+0x00F1F1F1F1F10000, 0x00DDDDDDDDDD0000, 0x0059595959590000, 0x0014141414140000,
+0x006C6C6C6C6C0000, 0x0092929292920000, 0x0054545454540000, 0x00D0D0D0D0D00000,
+0x0078787878780000, 0x0070707070700000, 0x00E3E3E3E3E30000, 0x0049494949490000,
+0x0080808080800000, 0x0050505050500000, 0x00A7A7A7A7A70000, 0x00F6F6F6F6F60000,
+0x0077777777770000, 0x0093939393930000, 0x0086868686860000, 0x0083838383830000,
+0x002A2A2A2A2A0000, 0x00C7C7C7C7C70000, 0x005B5B5B5B5B0000, 0x00E9E9E9E9E90000,
+0x00EEEEEEEEEE0000, 0x008F8F8F8F8F0000, 0x0001010101010000, 0x003D3D3D3D3D0000 };
+
+const u64bit Camellia_SBOX3[256] = {
+0x3800383800383800, 0x4100414100414100, 0x1600161600161600, 0x7600767600767600,
+0xD900D9D900D9D900, 0x9300939300939300, 0x6000606000606000, 0xF200F2F200F2F200,
+0x7200727200727200, 0xC200C2C200C2C200, 0xAB00ABAB00ABAB00, 0x9A009A9A009A9A00,
+0x7500757500757500, 0x0600060600060600, 0x5700575700575700, 0xA000A0A000A0A000,
+0x9100919100919100, 0xF700F7F700F7F700, 0xB500B5B500B5B500, 0xC900C9C900C9C900,
+0xA200A2A200A2A200, 0x8C008C8C008C8C00, 0xD200D2D200D2D200, 0x9000909000909000,
+0xF600F6F600F6F600, 0x0700070700070700, 0xA700A7A700A7A700, 0x2700272700272700,
+0x8E008E8E008E8E00, 0xB200B2B200B2B200, 0x4900494900494900, 0xDE00DEDE00DEDE00,
+0x4300434300434300, 0x5C005C5C005C5C00, 0xD700D7D700D7D700, 0xC700C7C700C7C700,
+0x3E003E3E003E3E00, 0xF500F5F500F5F500, 0x8F008F8F008F8F00, 0x6700676700676700,
+0x1F001F1F001F1F00, 0x1800181800181800, 0x6E006E6E006E6E00, 0xAF00AFAF00AFAF00,
+0x2F002F2F002F2F00, 0xE200E2E200E2E200, 0x8500858500858500, 0x0D000D0D000D0D00,
+0x5300535300535300, 0xF000F0F000F0F000, 0x9C009C9C009C9C00, 0x6500656500656500,
+0xEA00EAEA00EAEA00, 0xA300A3A300A3A300, 0xAE00AEAE00AEAE00, 0x9E009E9E009E9E00,
+0xEC00ECEC00ECEC00, 0x8000808000808000, 0x2D002D2D002D2D00, 0x6B006B6B006B6B00,
+0xA800A8A800A8A800, 0x2B002B2B002B2B00, 0x3600363600363600, 0xA600A6A600A6A600,
+0xC500C5C500C5C500, 0x8600868600868600, 0x4D004D4D004D4D00, 0x3300333300333300,
+0xFD00FDFD00FDFD00, 0x6600666600666600, 0x5800585800585800, 0x9600969600969600,
+0x3A003A3A003A3A00, 0x0900090900090900, 0x9500959500959500, 0x1000101000101000,
+0x7800787800787800, 0xD800D8D800D8D800, 0x4200424200424200, 0xCC00CCCC00CCCC00,
+0xEF00EFEF00EFEF00, 0x2600262600262600, 0xE500E5E500E5E500, 0x6100616100616100,
+0x1A001A1A001A1A00, 0x3F003F3F003F3F00, 0x3B003B3B003B3B00, 0x8200828200828200,
+0xB600B6B600B6B600, 0xDB00DBDB00DBDB00, 0xD400D4D400D4D400, 0x9800989800989800,
+0xE800E8E800E8E800, 0x8B008B8B008B8B00, 0x0200020200020200, 0xEB00EBEB00EBEB00,
+0x0A000A0A000A0A00, 0x2C002C2C002C2C00, 0x1D001D1D001D1D00, 0xB000B0B000B0B000,
+0x6F006F6F006F6F00, 0x8D008D8D008D8D00, 0x8800888800888800, 0x0E000E0E000E0E00,
+0x1900191900191900, 0x8700878700878700, 0x4E004E4E004E4E00, 0x0B000B0B000B0B00,
+0xA900A9A900A9A900, 0x0C000C0C000C0C00, 0x7900797900797900, 0x1100111100111100,
+0x7F007F7F007F7F00, 0x2200222200222200, 0xE700E7E700E7E700, 0x5900595900595900,
+0xE100E1E100E1E100, 0xDA00DADA00DADA00, 0x3D003D3D003D3D00, 0xC800C8C800C8C800,
+0x1200121200121200, 0x0400040400040400, 0x7400747400747400, 0x5400545400545400,
+0x3000303000303000, 0x7E007E7E007E7E00, 0xB400B4B400B4B400, 0x2800282800282800,
+0x5500555500555500, 0x6800686800686800, 0x5000505000505000, 0xBE00BEBE00BEBE00,
+0xD000D0D000D0D000, 0xC400C4C400C4C400, 0x3100313100313100, 0xCB00CBCB00CBCB00,
+0x2A002A2A002A2A00, 0xAD00ADAD00ADAD00, 0x0F000F0F000F0F00, 0xCA00CACA00CACA00,
+0x7000707000707000, 0xFF00FFFF00FFFF00, 0x3200323200323200, 0x6900696900696900,
+0x0800080800080800, 0x6200626200626200, 0x0000000000000000, 0x2400242400242400,
+0xD100D1D100D1D100, 0xFB00FBFB00FBFB00, 0xBA00BABA00BABA00, 0xED00EDED00EDED00,
+0x4500454500454500, 0x8100818100818100, 0x7300737300737300, 0x6D006D6D006D6D00,
+0x8400848400848400, 0x9F009F9F009F9F00, 0xEE00EEEE00EEEE00, 0x4A004A4A004A4A00,
+0xC300C3C300C3C300, 0x2E002E2E002E2E00, 0xC100C1C100C1C100, 0x0100010100010100,
+0xE600E6E600E6E600, 0x2500252500252500, 0x4800484800484800, 0x9900999900999900,
+0xB900B9B900B9B900, 0xB300B3B300B3B300, 0x7B007B7B007B7B00, 0xF900F9F900F9F900,
+0xCE00CECE00CECE00, 0xBF00BFBF00BFBF00, 0xDF00DFDF00DFDF00, 0x7100717100717100,
+0x2900292900292900, 0xCD00CDCD00CDCD00, 0x6C006C6C006C6C00, 0x1300131300131300,
+0x6400646400646400, 0x9B009B9B009B9B00, 0x6300636300636300, 0x9D009D9D009D9D00,
+0xC000C0C000C0C000, 0x4B004B4B004B4B00, 0xB700B7B700B7B700, 0xA500A5A500A5A500,
+0x8900898900898900, 0x5F005F5F005F5F00, 0xB100B1B100B1B100, 0x1700171700171700,
+0xF400F4F400F4F400, 0xBC00BCBC00BCBC00, 0xD300D3D300D3D300, 0x4600464600464600,
+0xCF00CFCF00CFCF00, 0x3700373700373700, 0x5E005E5E005E5E00, 0x4700474700474700,
+0x9400949400949400, 0xFA00FAFA00FAFA00, 0xFC00FCFC00FCFC00, 0x5B005B5B005B5B00,
+0x9700979700979700, 0xFE00FEFE00FEFE00, 0x5A005A5A005A5A00, 0xAC00ACAC00ACAC00,
+0x3C003C3C003C3C00, 0x4C004C4C004C4C00, 0x0300030300030300, 0x3500353500353500,
+0xF300F3F300F3F300, 0x2300232300232300, 0xB800B8B800B8B800, 0x5D005D5D005D5D00,
+0x6A006A6A006A6A00, 0x9200929200929200, 0xD500D5D500D5D500, 0x2100212100212100,
+0x4400444400444400, 0x5100515100515100, 0xC600C6C600C6C600, 0x7D007D7D007D7D00,
+0x3900393900393900, 0x8300838300838300, 0xDC00DCDC00DCDC00, 0xAA00AAAA00AAAA00,
+0x7C007C7C007C7C00, 0x7700777700777700, 0x5600565600565600, 0x0500050500050500,
+0x1B001B1B001B1B00, 0xA400A4A400A4A400, 0x1500151500151500, 0x3400343400343400,
+0x1E001E1E001E1E00, 0x1C001C1C001C1C00, 0xF800F8F800F8F800, 0x5200525200525200,
+0x2000202000202000, 0x1400141400141400, 0xE900E9E900E9E900, 0xBD00BDBD00BDBD00,
+0xDD00DDDD00DDDD00, 0xE400E4E400E4E400, 0xA100A1A100A1A100, 0xE000E0E000E0E000,
+0x8A008A8A008A8A00, 0xF100F1F100F1F100, 0xD600D6D600D6D600, 0x7A007A7A007A7A00,
+0xBB00BBBB00BBBB00, 0xE300E3E300E3E300, 0x4000404000404000, 0x4F004F4F004F4F00 };
+
+const u64bit Camellia_SBOX4[256] = {
+0x7070007000007070, 0x2C2C002C00002C2C, 0xB3B300B30000B3B3, 0xC0C000C00000C0C0,
+0xE4E400E40000E4E4, 0x5757005700005757, 0xEAEA00EA0000EAEA, 0xAEAE00AE0000AEAE,
+0x2323002300002323, 0x6B6B006B00006B6B, 0x4545004500004545, 0xA5A500A50000A5A5,
+0xEDED00ED0000EDED, 0x4F4F004F00004F4F, 0x1D1D001D00001D1D, 0x9292009200009292,
+0x8686008600008686, 0xAFAF00AF0000AFAF, 0x7C7C007C00007C7C, 0x1F1F001F00001F1F,
+0x3E3E003E00003E3E, 0xDCDC00DC0000DCDC, 0x5E5E005E00005E5E, 0x0B0B000B00000B0B,
+0xA6A600A60000A6A6, 0x3939003900003939, 0xD5D500D50000D5D5, 0x5D5D005D00005D5D,
+0xD9D900D90000D9D9, 0x5A5A005A00005A5A, 0x5151005100005151, 0x6C6C006C00006C6C,
+0x8B8B008B00008B8B, 0x9A9A009A00009A9A, 0xFBFB00FB0000FBFB, 0xB0B000B00000B0B0,
+0x7474007400007474, 0x2B2B002B00002B2B, 0xF0F000F00000F0F0, 0x8484008400008484,
+0xDFDF00DF0000DFDF, 0xCBCB00CB0000CBCB, 0x3434003400003434, 0x7676007600007676,
+0x6D6D006D00006D6D, 0xA9A900A90000A9A9, 0xD1D100D10000D1D1, 0x0404000400000404,
+0x1414001400001414, 0x3A3A003A00003A3A, 0xDEDE00DE0000DEDE, 0x1111001100001111,
+0x3232003200003232, 0x9C9C009C00009C9C, 0x5353005300005353, 0xF2F200F20000F2F2,
+0xFEFE00FE0000FEFE, 0xCFCF00CF0000CFCF, 0xC3C300C30000C3C3, 0x7A7A007A00007A7A,
+0x2424002400002424, 0xE8E800E80000E8E8, 0x6060006000006060, 0x6969006900006969,
+0xAAAA00AA0000AAAA, 0xA0A000A00000A0A0, 0xA1A100A10000A1A1, 0x6262006200006262,
+0x5454005400005454, 0x1E1E001E00001E1E, 0xE0E000E00000E0E0, 0x6464006400006464,
+0x1010001000001010, 0x0000000000000000, 0xA3A300A30000A3A3, 0x7575007500007575,
+0x8A8A008A00008A8A, 0xE6E600E60000E6E6, 0x0909000900000909, 0xDDDD00DD0000DDDD,
+0x8787008700008787, 0x8383008300008383, 0xCDCD00CD0000CDCD, 0x9090009000009090,
+0x7373007300007373, 0xF6F600F60000F6F6, 0x9D9D009D00009D9D, 0xBFBF00BF0000BFBF,
+0x5252005200005252, 0xD8D800D80000D8D8, 0xC8C800C80000C8C8, 0xC6C600C60000C6C6,
+0x8181008100008181, 0x6F6F006F00006F6F, 0x1313001300001313, 0x6363006300006363,
+0xE9E900E90000E9E9, 0xA7A700A70000A7A7, 0x9F9F009F00009F9F, 0xBCBC00BC0000BCBC,
+0x2929002900002929, 0xF9F900F90000F9F9, 0x2F2F002F00002F2F, 0xB4B400B40000B4B4,
+0x7878007800007878, 0x0606000600000606, 0xE7E700E70000E7E7, 0x7171007100007171,
+0xD4D400D40000D4D4, 0xABAB00AB0000ABAB, 0x8888008800008888, 0x8D8D008D00008D8D,
+0x7272007200007272, 0xB9B900B90000B9B9, 0xF8F800F80000F8F8, 0xACAC00AC0000ACAC,
+0x3636003600003636, 0x2A2A002A00002A2A, 0x3C3C003C00003C3C, 0xF1F100F10000F1F1,
+0x4040004000004040, 0xD3D300D30000D3D3, 0xBBBB00BB0000BBBB, 0x4343004300004343,
+0x1515001500001515, 0xADAD00AD0000ADAD, 0x7777007700007777, 0x8080008000008080,
+0x8282008200008282, 0xECEC00EC0000ECEC, 0x2727002700002727, 0xE5E500E50000E5E5,
+0x8585008500008585, 0x3535003500003535, 0x0C0C000C00000C0C, 0x4141004100004141,
+0xEFEF00EF0000EFEF, 0x9393009300009393, 0x1919001900001919, 0x2121002100002121,
+0x0E0E000E00000E0E, 0x4E4E004E00004E4E, 0x6565006500006565, 0xBDBD00BD0000BDBD,
+0xB8B800B80000B8B8, 0x8F8F008F00008F8F, 0xEBEB00EB0000EBEB, 0xCECE00CE0000CECE,
+0x3030003000003030, 0x5F5F005F00005F5F, 0xC5C500C50000C5C5, 0x1A1A001A00001A1A,
+0xE1E100E10000E1E1, 0xCACA00CA0000CACA, 0x4747004700004747, 0x3D3D003D00003D3D,
+0x0101000100000101, 0xD6D600D60000D6D6, 0x5656005600005656, 0x4D4D004D00004D4D,
+0x0D0D000D00000D0D, 0x6666006600006666, 0xCCCC00CC0000CCCC, 0x2D2D002D00002D2D,
+0x1212001200001212, 0x2020002000002020, 0xB1B100B10000B1B1, 0x9999009900009999,
+0x4C4C004C00004C4C, 0xC2C200C20000C2C2, 0x7E7E007E00007E7E, 0x0505000500000505,
+0xB7B700B70000B7B7, 0x3131003100003131, 0x1717001700001717, 0xD7D700D70000D7D7,
+0x5858005800005858, 0x6161006100006161, 0x1B1B001B00001B1B, 0x1C1C001C00001C1C,
+0x0F0F000F00000F0F, 0x1616001600001616, 0x1818001800001818, 0x2222002200002222,
+0x4444004400004444, 0xB2B200B20000B2B2, 0xB5B500B50000B5B5, 0x9191009100009191,
+0x0808000800000808, 0xA8A800A80000A8A8, 0xFCFC00FC0000FCFC, 0x5050005000005050,
+0xD0D000D00000D0D0, 0x7D7D007D00007D7D, 0x8989008900008989, 0x9797009700009797,
+0x5B5B005B00005B5B, 0x9595009500009595, 0xFFFF00FF0000FFFF, 0xD2D200D20000D2D2,
+0xC4C400C40000C4C4, 0x4848004800004848, 0xF7F700F70000F7F7, 0xDBDB00DB0000DBDB,
+0x0303000300000303, 0xDADA00DA0000DADA, 0x3F3F003F00003F3F, 0x9494009400009494,
+0x5C5C005C00005C5C, 0x0202000200000202, 0x4A4A004A00004A4A, 0x3333003300003333,
+0x6767006700006767, 0xF3F300F30000F3F3, 0x7F7F007F00007F7F, 0xE2E200E20000E2E2,
+0x9B9B009B00009B9B, 0x2626002600002626, 0x3737003700003737, 0x3B3B003B00003B3B,
+0x9696009600009696, 0x4B4B004B00004B4B, 0xBEBE00BE0000BEBE, 0x2E2E002E00002E2E,
+0x7979007900007979, 0x8C8C008C00008C8C, 0x6E6E006E00006E6E, 0x8E8E008E00008E8E,
+0xF5F500F50000F5F5, 0xB6B600B60000B6B6, 0xFDFD00FD0000FDFD, 0x5959005900005959,
+0x9898009800009898, 0x6A6A006A00006A6A, 0x4646004600004646, 0xBABA00BA0000BABA,
+0x2525002500002525, 0x4242004200004242, 0xA2A200A20000A2A2, 0xFAFA00FA0000FAFA,
+0x0707000700000707, 0x5555005500005555, 0xEEEE00EE0000EEEE, 0x0A0A000A00000A0A,
+0x4949004900004949, 0x6868006800006868, 0x3838003800003838, 0xA4A400A40000A4A4,
+0x2828002800002828, 0x7B7B007B00007B7B, 0xC9C900C90000C9C9, 0xC1C100C10000C1C1,
+0xE3E300E30000E3E3, 0xF4F400F40000F4F4, 0xC7C700C70000C7C7, 0x9E9E009E00009E9E };
+
+const u64bit Camellia_SBOX5[256] = {
+0x00E0E0E000E0E0E0, 0x0005050500050505, 0x0058585800585858, 0x00D9D9D900D9D9D9,
+0x0067676700676767, 0x004E4E4E004E4E4E, 0x0081818100818181, 0x00CBCBCB00CBCBCB,
+0x00C9C9C900C9C9C9, 0x000B0B0B000B0B0B, 0x00AEAEAE00AEAEAE, 0x006A6A6A006A6A6A,
+0x00D5D5D500D5D5D5, 0x0018181800181818, 0x005D5D5D005D5D5D, 0x0082828200828282,
+0x0046464600464646, 0x00DFDFDF00DFDFDF, 0x00D6D6D600D6D6D6, 0x0027272700272727,
+0x008A8A8A008A8A8A, 0x0032323200323232, 0x004B4B4B004B4B4B, 0x0042424200424242,
+0x00DBDBDB00DBDBDB, 0x001C1C1C001C1C1C, 0x009E9E9E009E9E9E, 0x009C9C9C009C9C9C,
+0x003A3A3A003A3A3A, 0x00CACACA00CACACA, 0x0025252500252525, 0x007B7B7B007B7B7B,
+0x000D0D0D000D0D0D, 0x0071717100717171, 0x005F5F5F005F5F5F, 0x001F1F1F001F1F1F,
+0x00F8F8F800F8F8F8, 0x00D7D7D700D7D7D7, 0x003E3E3E003E3E3E, 0x009D9D9D009D9D9D,
+0x007C7C7C007C7C7C, 0x0060606000606060, 0x00B9B9B900B9B9B9, 0x00BEBEBE00BEBEBE,
+0x00BCBCBC00BCBCBC, 0x008B8B8B008B8B8B, 0x0016161600161616, 0x0034343400343434,
+0x004D4D4D004D4D4D, 0x00C3C3C300C3C3C3, 0x0072727200727272, 0x0095959500959595,
+0x00ABABAB00ABABAB, 0x008E8E8E008E8E8E, 0x00BABABA00BABABA, 0x007A7A7A007A7A7A,
+0x00B3B3B300B3B3B3, 0x0002020200020202, 0x00B4B4B400B4B4B4, 0x00ADADAD00ADADAD,
+0x00A2A2A200A2A2A2, 0x00ACACAC00ACACAC, 0x00D8D8D800D8D8D8, 0x009A9A9A009A9A9A,
+0x0017171700171717, 0x001A1A1A001A1A1A, 0x0035353500353535, 0x00CCCCCC00CCCCCC,
+0x00F7F7F700F7F7F7, 0x0099999900999999, 0x0061616100616161, 0x005A5A5A005A5A5A,
+0x00E8E8E800E8E8E8, 0x0024242400242424, 0x0056565600565656, 0x0040404000404040,
+0x00E1E1E100E1E1E1, 0x0063636300636363, 0x0009090900090909, 0x0033333300333333,
+0x00BFBFBF00BFBFBF, 0x0098989800989898, 0x0097979700979797, 0x0085858500858585,
+0x0068686800686868, 0x00FCFCFC00FCFCFC, 0x00ECECEC00ECECEC, 0x000A0A0A000A0A0A,
+0x00DADADA00DADADA, 0x006F6F6F006F6F6F, 0x0053535300535353, 0x0062626200626262,
+0x00A3A3A300A3A3A3, 0x002E2E2E002E2E2E, 0x0008080800080808, 0x00AFAFAF00AFAFAF,
+0x0028282800282828, 0x00B0B0B000B0B0B0, 0x0074747400747474, 0x00C2C2C200C2C2C2,
+0x00BDBDBD00BDBDBD, 0x0036363600363636, 0x0022222200222222, 0x0038383800383838,
+0x0064646400646464, 0x001E1E1E001E1E1E, 0x0039393900393939, 0x002C2C2C002C2C2C,
+0x00A6A6A600A6A6A6, 0x0030303000303030, 0x00E5E5E500E5E5E5, 0x0044444400444444,
+0x00FDFDFD00FDFDFD, 0x0088888800888888, 0x009F9F9F009F9F9F, 0x0065656500656565,
+0x0087878700878787, 0x006B6B6B006B6B6B, 0x00F4F4F400F4F4F4, 0x0023232300232323,
+0x0048484800484848, 0x0010101000101010, 0x00D1D1D100D1D1D1, 0x0051515100515151,
+0x00C0C0C000C0C0C0, 0x00F9F9F900F9F9F9, 0x00D2D2D200D2D2D2, 0x00A0A0A000A0A0A0,
+0x0055555500555555, 0x00A1A1A100A1A1A1, 0x0041414100414141, 0x00FAFAFA00FAFAFA,
+0x0043434300434343, 0x0013131300131313, 0x00C4C4C400C4C4C4, 0x002F2F2F002F2F2F,
+0x00A8A8A800A8A8A8, 0x00B6B6B600B6B6B6, 0x003C3C3C003C3C3C, 0x002B2B2B002B2B2B,
+0x00C1C1C100C1C1C1, 0x00FFFFFF00FFFFFF, 0x00C8C8C800C8C8C8, 0x00A5A5A500A5A5A5,
+0x0020202000202020, 0x0089898900898989, 0x0000000000000000, 0x0090909000909090,
+0x0047474700474747, 0x00EFEFEF00EFEFEF, 0x00EAEAEA00EAEAEA, 0x00B7B7B700B7B7B7,
+0x0015151500151515, 0x0006060600060606, 0x00CDCDCD00CDCDCD, 0x00B5B5B500B5B5B5,
+0x0012121200121212, 0x007E7E7E007E7E7E, 0x00BBBBBB00BBBBBB, 0x0029292900292929,
+0x000F0F0F000F0F0F, 0x00B8B8B800B8B8B8, 0x0007070700070707, 0x0004040400040404,
+0x009B9B9B009B9B9B, 0x0094949400949494, 0x0021212100212121, 0x0066666600666666,
+0x00E6E6E600E6E6E6, 0x00CECECE00CECECE, 0x00EDEDED00EDEDED, 0x00E7E7E700E7E7E7,
+0x003B3B3B003B3B3B, 0x00FEFEFE00FEFEFE, 0x007F7F7F007F7F7F, 0x00C5C5C500C5C5C5,
+0x00A4A4A400A4A4A4, 0x0037373700373737, 0x00B1B1B100B1B1B1, 0x004C4C4C004C4C4C,
+0x0091919100919191, 0x006E6E6E006E6E6E, 0x008D8D8D008D8D8D, 0x0076767600767676,
+0x0003030300030303, 0x002D2D2D002D2D2D, 0x00DEDEDE00DEDEDE, 0x0096969600969696,
+0x0026262600262626, 0x007D7D7D007D7D7D, 0x00C6C6C600C6C6C6, 0x005C5C5C005C5C5C,
+0x00D3D3D300D3D3D3, 0x00F2F2F200F2F2F2, 0x004F4F4F004F4F4F, 0x0019191900191919,
+0x003F3F3F003F3F3F, 0x00DCDCDC00DCDCDC, 0x0079797900797979, 0x001D1D1D001D1D1D,
+0x0052525200525252, 0x00EBEBEB00EBEBEB, 0x00F3F3F300F3F3F3, 0x006D6D6D006D6D6D,
+0x005E5E5E005E5E5E, 0x00FBFBFB00FBFBFB, 0x0069696900696969, 0x00B2B2B200B2B2B2,
+0x00F0F0F000F0F0F0, 0x0031313100313131, 0x000C0C0C000C0C0C, 0x00D4D4D400D4D4D4,
+0x00CFCFCF00CFCFCF, 0x008C8C8C008C8C8C, 0x00E2E2E200E2E2E2, 0x0075757500757575,
+0x00A9A9A900A9A9A9, 0x004A4A4A004A4A4A, 0x0057575700575757, 0x0084848400848484,
+0x0011111100111111, 0x0045454500454545, 0x001B1B1B001B1B1B, 0x00F5F5F500F5F5F5,
+0x00E4E4E400E4E4E4, 0x000E0E0E000E0E0E, 0x0073737300737373, 0x00AAAAAA00AAAAAA,
+0x00F1F1F100F1F1F1, 0x00DDDDDD00DDDDDD, 0x0059595900595959, 0x0014141400141414,
+0x006C6C6C006C6C6C, 0x0092929200929292, 0x0054545400545454, 0x00D0D0D000D0D0D0,
+0x0078787800787878, 0x0070707000707070, 0x00E3E3E300E3E3E3, 0x0049494900494949,
+0x0080808000808080, 0x0050505000505050, 0x00A7A7A700A7A7A7, 0x00F6F6F600F6F6F6,
+0x0077777700777777, 0x0093939300939393, 0x0086868600868686, 0x0083838300838383,
+0x002A2A2A002A2A2A, 0x00C7C7C700C7C7C7, 0x005B5B5B005B5B5B, 0x00E9E9E900E9E9E9,
+0x00EEEEEE00EEEEEE, 0x008F8F8F008F8F8F, 0x0001010100010101, 0x003D3D3D003D3D3D };
+
+const u64bit Camellia_SBOX6[256] = {
+0x3800383838003838, 0x4100414141004141, 0x1600161616001616, 0x7600767676007676,
+0xD900D9D9D900D9D9, 0x9300939393009393, 0x6000606060006060, 0xF200F2F2F200F2F2,
+0x7200727272007272, 0xC200C2C2C200C2C2, 0xAB00ABABAB00ABAB, 0x9A009A9A9A009A9A,
+0x7500757575007575, 0x0600060606000606, 0x5700575757005757, 0xA000A0A0A000A0A0,
+0x9100919191009191, 0xF700F7F7F700F7F7, 0xB500B5B5B500B5B5, 0xC900C9C9C900C9C9,
+0xA200A2A2A200A2A2, 0x8C008C8C8C008C8C, 0xD200D2D2D200D2D2, 0x9000909090009090,
+0xF600F6F6F600F6F6, 0x0700070707000707, 0xA700A7A7A700A7A7, 0x2700272727002727,
+0x8E008E8E8E008E8E, 0xB200B2B2B200B2B2, 0x4900494949004949, 0xDE00DEDEDE00DEDE,
+0x4300434343004343, 0x5C005C5C5C005C5C, 0xD700D7D7D700D7D7, 0xC700C7C7C700C7C7,
+0x3E003E3E3E003E3E, 0xF500F5F5F500F5F5, 0x8F008F8F8F008F8F, 0x6700676767006767,
+0x1F001F1F1F001F1F, 0x1800181818001818, 0x6E006E6E6E006E6E, 0xAF00AFAFAF00AFAF,
+0x2F002F2F2F002F2F, 0xE200E2E2E200E2E2, 0x8500858585008585, 0x0D000D0D0D000D0D,
+0x5300535353005353, 0xF000F0F0F000F0F0, 0x9C009C9C9C009C9C, 0x6500656565006565,
+0xEA00EAEAEA00EAEA, 0xA300A3A3A300A3A3, 0xAE00AEAEAE00AEAE, 0x9E009E9E9E009E9E,
+0xEC00ECECEC00ECEC, 0x8000808080008080, 0x2D002D2D2D002D2D, 0x6B006B6B6B006B6B,
+0xA800A8A8A800A8A8, 0x2B002B2B2B002B2B, 0x3600363636003636, 0xA600A6A6A600A6A6,
+0xC500C5C5C500C5C5, 0x8600868686008686, 0x4D004D4D4D004D4D, 0x3300333333003333,
+0xFD00FDFDFD00FDFD, 0x6600666666006666, 0x5800585858005858, 0x9600969696009696,
+0x3A003A3A3A003A3A, 0x0900090909000909, 0x9500959595009595, 0x1000101010001010,
+0x7800787878007878, 0xD800D8D8D800D8D8, 0x4200424242004242, 0xCC00CCCCCC00CCCC,
+0xEF00EFEFEF00EFEF, 0x2600262626002626, 0xE500E5E5E500E5E5, 0x6100616161006161,
+0x1A001A1A1A001A1A, 0x3F003F3F3F003F3F, 0x3B003B3B3B003B3B, 0x8200828282008282,
+0xB600B6B6B600B6B6, 0xDB00DBDBDB00DBDB, 0xD400D4D4D400D4D4, 0x9800989898009898,
+0xE800E8E8E800E8E8, 0x8B008B8B8B008B8B, 0x0200020202000202, 0xEB00EBEBEB00EBEB,
+0x0A000A0A0A000A0A, 0x2C002C2C2C002C2C, 0x1D001D1D1D001D1D, 0xB000B0B0B000B0B0,
+0x6F006F6F6F006F6F, 0x8D008D8D8D008D8D, 0x8800888888008888, 0x0E000E0E0E000E0E,
+0x1900191919001919, 0x8700878787008787, 0x4E004E4E4E004E4E, 0x0B000B0B0B000B0B,
+0xA900A9A9A900A9A9, 0x0C000C0C0C000C0C, 0x7900797979007979, 0x1100111111001111,
+0x7F007F7F7F007F7F, 0x2200222222002222, 0xE700E7E7E700E7E7, 0x5900595959005959,
+0xE100E1E1E100E1E1, 0xDA00DADADA00DADA, 0x3D003D3D3D003D3D, 0xC800C8C8C800C8C8,
+0x1200121212001212, 0x0400040404000404, 0x7400747474007474, 0x5400545454005454,
+0x3000303030003030, 0x7E007E7E7E007E7E, 0xB400B4B4B400B4B4, 0x2800282828002828,
+0x5500555555005555, 0x6800686868006868, 0x5000505050005050, 0xBE00BEBEBE00BEBE,
+0xD000D0D0D000D0D0, 0xC400C4C4C400C4C4, 0x3100313131003131, 0xCB00CBCBCB00CBCB,
+0x2A002A2A2A002A2A, 0xAD00ADADAD00ADAD, 0x0F000F0F0F000F0F, 0xCA00CACACA00CACA,
+0x7000707070007070, 0xFF00FFFFFF00FFFF, 0x3200323232003232, 0x6900696969006969,
+0x0800080808000808, 0x6200626262006262, 0x0000000000000000, 0x2400242424002424,
+0xD100D1D1D100D1D1, 0xFB00FBFBFB00FBFB, 0xBA00BABABA00BABA, 0xED00EDEDED00EDED,
+0x4500454545004545, 0x8100818181008181, 0x7300737373007373, 0x6D006D6D6D006D6D,
+0x8400848484008484, 0x9F009F9F9F009F9F, 0xEE00EEEEEE00EEEE, 0x4A004A4A4A004A4A,
+0xC300C3C3C300C3C3, 0x2E002E2E2E002E2E, 0xC100C1C1C100C1C1, 0x0100010101000101,
+0xE600E6E6E600E6E6, 0x2500252525002525, 0x4800484848004848, 0x9900999999009999,
+0xB900B9B9B900B9B9, 0xB300B3B3B300B3B3, 0x7B007B7B7B007B7B, 0xF900F9F9F900F9F9,
+0xCE00CECECE00CECE, 0xBF00BFBFBF00BFBF, 0xDF00DFDFDF00DFDF, 0x7100717171007171,
+0x2900292929002929, 0xCD00CDCDCD00CDCD, 0x6C006C6C6C006C6C, 0x1300131313001313,
+0x6400646464006464, 0x9B009B9B9B009B9B, 0x6300636363006363, 0x9D009D9D9D009D9D,
+0xC000C0C0C000C0C0, 0x4B004B4B4B004B4B, 0xB700B7B7B700B7B7, 0xA500A5A5A500A5A5,
+0x8900898989008989, 0x5F005F5F5F005F5F, 0xB100B1B1B100B1B1, 0x1700171717001717,
+0xF400F4F4F400F4F4, 0xBC00BCBCBC00BCBC, 0xD300D3D3D300D3D3, 0x4600464646004646,
+0xCF00CFCFCF00CFCF, 0x3700373737003737, 0x5E005E5E5E005E5E, 0x4700474747004747,
+0x9400949494009494, 0xFA00FAFAFA00FAFA, 0xFC00FCFCFC00FCFC, 0x5B005B5B5B005B5B,
+0x9700979797009797, 0xFE00FEFEFE00FEFE, 0x5A005A5A5A005A5A, 0xAC00ACACAC00ACAC,
+0x3C003C3C3C003C3C, 0x4C004C4C4C004C4C, 0x0300030303000303, 0x3500353535003535,
+0xF300F3F3F300F3F3, 0x2300232323002323, 0xB800B8B8B800B8B8, 0x5D005D5D5D005D5D,
+0x6A006A6A6A006A6A, 0x9200929292009292, 0xD500D5D5D500D5D5, 0x2100212121002121,
+0x4400444444004444, 0x5100515151005151, 0xC600C6C6C600C6C6, 0x7D007D7D7D007D7D,
+0x3900393939003939, 0x8300838383008383, 0xDC00DCDCDC00DCDC, 0xAA00AAAAAA00AAAA,
+0x7C007C7C7C007C7C, 0x7700777777007777, 0x5600565656005656, 0x0500050505000505,
+0x1B001B1B1B001B1B, 0xA400A4A4A400A4A4, 0x1500151515001515, 0x3400343434003434,
+0x1E001E1E1E001E1E, 0x1C001C1C1C001C1C, 0xF800F8F8F800F8F8, 0x5200525252005252,
+0x2000202020002020, 0x1400141414001414, 0xE900E9E9E900E9E9, 0xBD00BDBDBD00BDBD,
+0xDD00DDDDDD00DDDD, 0xE400E4E4E400E4E4, 0xA100A1A1A100A1A1, 0xE000E0E0E000E0E0,
+0x8A008A8A8A008A8A, 0xF100F1F1F100F1F1, 0xD600D6D6D600D6D6, 0x7A007A7A7A007A7A,
+0xBB00BBBBBB00BBBB, 0xE300E3E3E300E3E3, 0x4000404040004040, 0x4F004F4F4F004F4F };
+
+const u64bit Camellia_SBOX7[256] = {
+0x7070007070700070, 0x2C2C002C2C2C002C, 0xB3B300B3B3B300B3, 0xC0C000C0C0C000C0,
+0xE4E400E4E4E400E4, 0x5757005757570057, 0xEAEA00EAEAEA00EA, 0xAEAE00AEAEAE00AE,
+0x2323002323230023, 0x6B6B006B6B6B006B, 0x4545004545450045, 0xA5A500A5A5A500A5,
+0xEDED00EDEDED00ED, 0x4F4F004F4F4F004F, 0x1D1D001D1D1D001D, 0x9292009292920092,
+0x8686008686860086, 0xAFAF00AFAFAF00AF, 0x7C7C007C7C7C007C, 0x1F1F001F1F1F001F,
+0x3E3E003E3E3E003E, 0xDCDC00DCDCDC00DC, 0x5E5E005E5E5E005E, 0x0B0B000B0B0B000B,
+0xA6A600A6A6A600A6, 0x3939003939390039, 0xD5D500D5D5D500D5, 0x5D5D005D5D5D005D,
+0xD9D900D9D9D900D9, 0x5A5A005A5A5A005A, 0x5151005151510051, 0x6C6C006C6C6C006C,
+0x8B8B008B8B8B008B, 0x9A9A009A9A9A009A, 0xFBFB00FBFBFB00FB, 0xB0B000B0B0B000B0,
+0x7474007474740074, 0x2B2B002B2B2B002B, 0xF0F000F0F0F000F0, 0x8484008484840084,
+0xDFDF00DFDFDF00DF, 0xCBCB00CBCBCB00CB, 0x3434003434340034, 0x7676007676760076,
+0x6D6D006D6D6D006D, 0xA9A900A9A9A900A9, 0xD1D100D1D1D100D1, 0x0404000404040004,
+0x1414001414140014, 0x3A3A003A3A3A003A, 0xDEDE00DEDEDE00DE, 0x1111001111110011,
+0x3232003232320032, 0x9C9C009C9C9C009C, 0x5353005353530053, 0xF2F200F2F2F200F2,
+0xFEFE00FEFEFE00FE, 0xCFCF00CFCFCF00CF, 0xC3C300C3C3C300C3, 0x7A7A007A7A7A007A,
+0x2424002424240024, 0xE8E800E8E8E800E8, 0x6060006060600060, 0x6969006969690069,
+0xAAAA00AAAAAA00AA, 0xA0A000A0A0A000A0, 0xA1A100A1A1A100A1, 0x6262006262620062,
+0x5454005454540054, 0x1E1E001E1E1E001E, 0xE0E000E0E0E000E0, 0x6464006464640064,
+0x1010001010100010, 0x0000000000000000, 0xA3A300A3A3A300A3, 0x7575007575750075,
+0x8A8A008A8A8A008A, 0xE6E600E6E6E600E6, 0x0909000909090009, 0xDDDD00DDDDDD00DD,
+0x8787008787870087, 0x8383008383830083, 0xCDCD00CDCDCD00CD, 0x9090009090900090,
+0x7373007373730073, 0xF6F600F6F6F600F6, 0x9D9D009D9D9D009D, 0xBFBF00BFBFBF00BF,
+0x5252005252520052, 0xD8D800D8D8D800D8, 0xC8C800C8C8C800C8, 0xC6C600C6C6C600C6,
+0x8181008181810081, 0x6F6F006F6F6F006F, 0x1313001313130013, 0x6363006363630063,
+0xE9E900E9E9E900E9, 0xA7A700A7A7A700A7, 0x9F9F009F9F9F009F, 0xBCBC00BCBCBC00BC,
+0x2929002929290029, 0xF9F900F9F9F900F9, 0x2F2F002F2F2F002F, 0xB4B400B4B4B400B4,
+0x7878007878780078, 0x0606000606060006, 0xE7E700E7E7E700E7, 0x7171007171710071,
+0xD4D400D4D4D400D4, 0xABAB00ABABAB00AB, 0x8888008888880088, 0x8D8D008D8D8D008D,
+0x7272007272720072, 0xB9B900B9B9B900B9, 0xF8F800F8F8F800F8, 0xACAC00ACACAC00AC,
+0x3636003636360036, 0x2A2A002A2A2A002A, 0x3C3C003C3C3C003C, 0xF1F100F1F1F100F1,
+0x4040004040400040, 0xD3D300D3D3D300D3, 0xBBBB00BBBBBB00BB, 0x4343004343430043,
+0x1515001515150015, 0xADAD00ADADAD00AD, 0x7777007777770077, 0x8080008080800080,
+0x8282008282820082, 0xECEC00ECECEC00EC, 0x2727002727270027, 0xE5E500E5E5E500E5,
+0x8585008585850085, 0x3535003535350035, 0x0C0C000C0C0C000C, 0x4141004141410041,
+0xEFEF00EFEFEF00EF, 0x9393009393930093, 0x1919001919190019, 0x2121002121210021,
+0x0E0E000E0E0E000E, 0x4E4E004E4E4E004E, 0x6565006565650065, 0xBDBD00BDBDBD00BD,
+0xB8B800B8B8B800B8, 0x8F8F008F8F8F008F, 0xEBEB00EBEBEB00EB, 0xCECE00CECECE00CE,
+0x3030003030300030, 0x5F5F005F5F5F005F, 0xC5C500C5C5C500C5, 0x1A1A001A1A1A001A,
+0xE1E100E1E1E100E1, 0xCACA00CACACA00CA, 0x4747004747470047, 0x3D3D003D3D3D003D,
+0x0101000101010001, 0xD6D600D6D6D600D6, 0x5656005656560056, 0x4D4D004D4D4D004D,
+0x0D0D000D0D0D000D, 0x6666006666660066, 0xCCCC00CCCCCC00CC, 0x2D2D002D2D2D002D,
+0x1212001212120012, 0x2020002020200020, 0xB1B100B1B1B100B1, 0x9999009999990099,
+0x4C4C004C4C4C004C, 0xC2C200C2C2C200C2, 0x7E7E007E7E7E007E, 0x0505000505050005,
+0xB7B700B7B7B700B7, 0x3131003131310031, 0x1717001717170017, 0xD7D700D7D7D700D7,
+0x5858005858580058, 0x6161006161610061, 0x1B1B001B1B1B001B, 0x1C1C001C1C1C001C,
+0x0F0F000F0F0F000F, 0x1616001616160016, 0x1818001818180018, 0x2222002222220022,
+0x4444004444440044, 0xB2B200B2B2B200B2, 0xB5B500B5B5B500B5, 0x9191009191910091,
+0x0808000808080008, 0xA8A800A8A8A800A8, 0xFCFC00FCFCFC00FC, 0x5050005050500050,
+0xD0D000D0D0D000D0, 0x7D7D007D7D7D007D, 0x8989008989890089, 0x9797009797970097,
+0x5B5B005B5B5B005B, 0x9595009595950095, 0xFFFF00FFFFFF00FF, 0xD2D200D2D2D200D2,
+0xC4C400C4C4C400C4, 0x4848004848480048, 0xF7F700F7F7F700F7, 0xDBDB00DBDBDB00DB,
+0x0303000303030003, 0xDADA00DADADA00DA, 0x3F3F003F3F3F003F, 0x9494009494940094,
+0x5C5C005C5C5C005C, 0x0202000202020002, 0x4A4A004A4A4A004A, 0x3333003333330033,
+0x6767006767670067, 0xF3F300F3F3F300F3, 0x7F7F007F7F7F007F, 0xE2E200E2E2E200E2,
+0x9B9B009B9B9B009B, 0x2626002626260026, 0x3737003737370037, 0x3B3B003B3B3B003B,
+0x9696009696960096, 0x4B4B004B4B4B004B, 0xBEBE00BEBEBE00BE, 0x2E2E002E2E2E002E,
+0x7979007979790079, 0x8C8C008C8C8C008C, 0x6E6E006E6E6E006E, 0x8E8E008E8E8E008E,
+0xF5F500F5F5F500F5, 0xB6B600B6B6B600B6, 0xFDFD00FDFDFD00FD, 0x5959005959590059,
+0x9898009898980098, 0x6A6A006A6A6A006A, 0x4646004646460046, 0xBABA00BABABA00BA,
+0x2525002525250025, 0x4242004242420042, 0xA2A200A2A2A200A2, 0xFAFA00FAFAFA00FA,
+0x0707000707070007, 0x5555005555550055, 0xEEEE00EEEEEE00EE, 0x0A0A000A0A0A000A,
+0x4949004949490049, 0x6868006868680068, 0x3838003838380038, 0xA4A400A4A4A400A4,
+0x2828002828280028, 0x7B7B007B7B7B007B, 0xC9C900C9C9C900C9, 0xC1C100C1C1C100C1,
+0xE3E300E3E3E300E3, 0xF4F400F4F4F400F4, 0xC7C700C7C7C700C7, 0x9E9E009E9E9E009E };
+
+const u64bit Camellia_SBOX8[256] = {
+0x7070700070707000, 0x8282820082828200, 0x2C2C2C002C2C2C00, 0xECECEC00ECECEC00,
+0xB3B3B300B3B3B300, 0x2727270027272700, 0xC0C0C000C0C0C000, 0xE5E5E500E5E5E500,
+0xE4E4E400E4E4E400, 0x8585850085858500, 0x5757570057575700, 0x3535350035353500,
+0xEAEAEA00EAEAEA00, 0x0C0C0C000C0C0C00, 0xAEAEAE00AEAEAE00, 0x4141410041414100,
+0x2323230023232300, 0xEFEFEF00EFEFEF00, 0x6B6B6B006B6B6B00, 0x9393930093939300,
+0x4545450045454500, 0x1919190019191900, 0xA5A5A500A5A5A500, 0x2121210021212100,
+0xEDEDED00EDEDED00, 0x0E0E0E000E0E0E00, 0x4F4F4F004F4F4F00, 0x4E4E4E004E4E4E00,
+0x1D1D1D001D1D1D00, 0x6565650065656500, 0x9292920092929200, 0xBDBDBD00BDBDBD00,
+0x8686860086868600, 0xB8B8B800B8B8B800, 0xAFAFAF00AFAFAF00, 0x8F8F8F008F8F8F00,
+0x7C7C7C007C7C7C00, 0xEBEBEB00EBEBEB00, 0x1F1F1F001F1F1F00, 0xCECECE00CECECE00,
+0x3E3E3E003E3E3E00, 0x3030300030303000, 0xDCDCDC00DCDCDC00, 0x5F5F5F005F5F5F00,
+0x5E5E5E005E5E5E00, 0xC5C5C500C5C5C500, 0x0B0B0B000B0B0B00, 0x1A1A1A001A1A1A00,
+0xA6A6A600A6A6A600, 0xE1E1E100E1E1E100, 0x3939390039393900, 0xCACACA00CACACA00,
+0xD5D5D500D5D5D500, 0x4747470047474700, 0x5D5D5D005D5D5D00, 0x3D3D3D003D3D3D00,
+0xD9D9D900D9D9D900, 0x0101010001010100, 0x5A5A5A005A5A5A00, 0xD6D6D600D6D6D600,
+0x5151510051515100, 0x5656560056565600, 0x6C6C6C006C6C6C00, 0x4D4D4D004D4D4D00,
+0x8B8B8B008B8B8B00, 0x0D0D0D000D0D0D00, 0x9A9A9A009A9A9A00, 0x6666660066666600,
+0xFBFBFB00FBFBFB00, 0xCCCCCC00CCCCCC00, 0xB0B0B000B0B0B000, 0x2D2D2D002D2D2D00,
+0x7474740074747400, 0x1212120012121200, 0x2B2B2B002B2B2B00, 0x2020200020202000,
+0xF0F0F000F0F0F000, 0xB1B1B100B1B1B100, 0x8484840084848400, 0x9999990099999900,
+0xDFDFDF00DFDFDF00, 0x4C4C4C004C4C4C00, 0xCBCBCB00CBCBCB00, 0xC2C2C200C2C2C200,
+0x3434340034343400, 0x7E7E7E007E7E7E00, 0x7676760076767600, 0x0505050005050500,
+0x6D6D6D006D6D6D00, 0xB7B7B700B7B7B700, 0xA9A9A900A9A9A900, 0x3131310031313100,
+0xD1D1D100D1D1D100, 0x1717170017171700, 0x0404040004040400, 0xD7D7D700D7D7D700,
+0x1414140014141400, 0x5858580058585800, 0x3A3A3A003A3A3A00, 0x6161610061616100,
+0xDEDEDE00DEDEDE00, 0x1B1B1B001B1B1B00, 0x1111110011111100, 0x1C1C1C001C1C1C00,
+0x3232320032323200, 0x0F0F0F000F0F0F00, 0x9C9C9C009C9C9C00, 0x1616160016161600,
+0x5353530053535300, 0x1818180018181800, 0xF2F2F200F2F2F200, 0x2222220022222200,
+0xFEFEFE00FEFEFE00, 0x4444440044444400, 0xCFCFCF00CFCFCF00, 0xB2B2B200B2B2B200,
+0xC3C3C300C3C3C300, 0xB5B5B500B5B5B500, 0x7A7A7A007A7A7A00, 0x9191910091919100,
+0x2424240024242400, 0x0808080008080800, 0xE8E8E800E8E8E800, 0xA8A8A800A8A8A800,
+0x6060600060606000, 0xFCFCFC00FCFCFC00, 0x6969690069696900, 0x5050500050505000,
+0xAAAAAA00AAAAAA00, 0xD0D0D000D0D0D000, 0xA0A0A000A0A0A000, 0x7D7D7D007D7D7D00,
+0xA1A1A100A1A1A100, 0x8989890089898900, 0x6262620062626200, 0x9797970097979700,
+0x5454540054545400, 0x5B5B5B005B5B5B00, 0x1E1E1E001E1E1E00, 0x9595950095959500,
+0xE0E0E000E0E0E000, 0xFFFFFF00FFFFFF00, 0x6464640064646400, 0xD2D2D200D2D2D200,
+0x1010100010101000, 0xC4C4C400C4C4C400, 0x0000000000000000, 0x4848480048484800,
+0xA3A3A300A3A3A300, 0xF7F7F700F7F7F700, 0x7575750075757500, 0xDBDBDB00DBDBDB00,
+0x8A8A8A008A8A8A00, 0x0303030003030300, 0xE6E6E600E6E6E600, 0xDADADA00DADADA00,
+0x0909090009090900, 0x3F3F3F003F3F3F00, 0xDDDDDD00DDDDDD00, 0x9494940094949400,
+0x8787870087878700, 0x5C5C5C005C5C5C00, 0x8383830083838300, 0x0202020002020200,
+0xCDCDCD00CDCDCD00, 0x4A4A4A004A4A4A00, 0x9090900090909000, 0x3333330033333300,
+0x7373730073737300, 0x6767670067676700, 0xF6F6F600F6F6F600, 0xF3F3F300F3F3F300,
+0x9D9D9D009D9D9D00, 0x7F7F7F007F7F7F00, 0xBFBFBF00BFBFBF00, 0xE2E2E200E2E2E200,
+0x5252520052525200, 0x9B9B9B009B9B9B00, 0xD8D8D800D8D8D800, 0x2626260026262600,
+0xC8C8C800C8C8C800, 0x3737370037373700, 0xC6C6C600C6C6C600, 0x3B3B3B003B3B3B00,
+0x8181810081818100, 0x9696960096969600, 0x6F6F6F006F6F6F00, 0x4B4B4B004B4B4B00,
+0x1313130013131300, 0xBEBEBE00BEBEBE00, 0x6363630063636300, 0x2E2E2E002E2E2E00,
+0xE9E9E900E9E9E900, 0x7979790079797900, 0xA7A7A700A7A7A700, 0x8C8C8C008C8C8C00,
+0x9F9F9F009F9F9F00, 0x6E6E6E006E6E6E00, 0xBCBCBC00BCBCBC00, 0x8E8E8E008E8E8E00,
+0x2929290029292900, 0xF5F5F500F5F5F500, 0xF9F9F900F9F9F900, 0xB6B6B600B6B6B600,
+0x2F2F2F002F2F2F00, 0xFDFDFD00FDFDFD00, 0xB4B4B400B4B4B400, 0x5959590059595900,
+0x7878780078787800, 0x9898980098989800, 0x0606060006060600, 0x6A6A6A006A6A6A00,
+0xE7E7E700E7E7E700, 0x4646460046464600, 0x7171710071717100, 0xBABABA00BABABA00,
+0xD4D4D400D4D4D400, 0x2525250025252500, 0xABABAB00ABABAB00, 0x4242420042424200,
+0x8888880088888800, 0xA2A2A200A2A2A200, 0x8D8D8D008D8D8D00, 0xFAFAFA00FAFAFA00,
+0x7272720072727200, 0x0707070007070700, 0xB9B9B900B9B9B900, 0x5555550055555500,
+0xF8F8F800F8F8F800, 0xEEEEEE00EEEEEE00, 0xACACAC00ACACAC00, 0x0A0A0A000A0A0A00,
+0x3636360036363600, 0x4949490049494900, 0x2A2A2A002A2A2A00, 0x6868680068686800,
+0x3C3C3C003C3C3C00, 0x3838380038383800, 0xF1F1F100F1F1F100, 0xA4A4A400A4A4A400,
+0x4040400040404000, 0x2828280028282800, 0xD3D3D300D3D3D300, 0x7B7B7B007B7B7B00,
+0xBBBBBB00BBBBBB00, 0xC9C9C900C9C9C900, 0x4343430043434300, 0xC1C1C100C1C1C100,
+0x1515150015151500, 0xE3E3E300E3E3E300, 0xADADAD00ADADAD00, 0xF4F4F400F4F4F400,
+0x7777770077777700, 0xC7C7C700C7C7C700, 0x8080800080808000, 0x9E9E9E009E9E9E00 };
+
+}
+
+#endif
diff --git a/src/block/camellia/info.txt b/src/block/camellia/info.txt
index cdb7b3d25..eb8d6c411 100644
--- a/src/block/camellia/info.txt
+++ b/src/block/camellia/info.txt
@@ -1 +1,9 @@
define CAMELLIA
+
+<header:internal>
+camellia_sbox.h
+</header:internal>
+
+<header:public>
+camellia.h
+</header:public>
diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp
index 24469e025..d64523c8b 100644
--- a/src/block/cast/cast128.cpp
+++ b/src/block/cast/cast128.cpp
@@ -16,7 +16,7 @@ namespace {
/*
* CAST-128 Round Type 1
*/
-inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+inline void R1(u32bit& L, u32bit R, u32bit MK, byte RK)
{
u32bit T = rotate_left(MK + R, RK);
L ^= (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
@@ -26,7 +26,7 @@ inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK)
/*
* CAST-128 Round Type 2
*/
-inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+inline void R2(u32bit& L, u32bit R, u32bit MK, byte RK)
{
u32bit T = rotate_left(MK ^ R, RK);
L ^= (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] +
@@ -36,7 +36,7 @@ inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK)
/*
* CAST-128 Round Type 3
*/
-inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+inline void R3(u32bit& L, u32bit R, u32bit MK, byte RK)
{
u32bit T = rotate_left(MK - R, RK);
L ^= ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^
@@ -118,23 +118,27 @@ void CAST_128::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void CAST_128::key_schedule(const byte key[], size_t length)
{
- clear();
- SecureVector<u32bit> X(4);
- for(size_t j = 0; j != length; ++j)
- X[j/4] = (X[j/4] << 8) + key[j];
+ MK.resize(48);
+ RK.resize(48);
+
+ secure_vector<u32bit> X(4);
+ for(size_t i = 0; i != length; ++i)
+ X[i/4] = (X[i/4] << 8) + key[i];
cast_ks(MK, X);
- cast_ks(RK, X);
- for(size_t j = 0; j != 16; ++j)
- RK[j] %= 32;
+ secure_vector<u32bit> RK32(48);
+ cast_ks(RK32, X);
+
+ for(size_t i = 0; i != 16; ++i)
+ RK[i] = RK32[i] % 32;
}
/*
* S-Box Based Key Expansion
*/
-void CAST_128::cast_ks(MemoryRegion<u32bit>& K,
- MemoryRegion<u32bit>& X)
+void CAST_128::cast_ks(secure_vector<u32bit>& K,
+ secure_vector<u32bit>& X)
{
class ByteReader
{
@@ -145,7 +149,7 @@ void CAST_128::cast_ks(MemoryRegion<u32bit>& K,
const u32bit* X;
};
- SecureVector<u32bit> Z(4);
+ secure_vector<u32bit> Z(4);
ByteReader x(&X[0]), z(&Z[0]);
Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)];
diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h
index 10c646c94..f3f23b14a 100644
--- a/src/block/cast/cast128.h
+++ b/src/block/cast/cast128.h
@@ -21,23 +21,23 @@ class BOTAN_DLL CAST_128 : public Block_Cipher_Fixed_Params<8, 11, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(MK); zeroise(RK); }
+ void clear() { MK.clear(); RK.clear(); }
std::string name() const { return "CAST-128"; }
BlockCipher* clone() const { return new CAST_128; }
- CAST_128() : MK(16), RK(16) {}
private:
void key_schedule(const byte[], size_t);
- static void cast_ks(MemoryRegion<u32bit>& ks,
- MemoryRegion<u32bit>& user_key);
+ static void cast_ks(secure_vector<u32bit>& ks,
+ secure_vector<u32bit>& user_key);
static const u32bit S5[256];
static const u32bit S6[256];
static const u32bit S7[256];
static const u32bit S8[256];
- SecureVector<u32bit> MK, RK;
+ secure_vector<u32bit> MK;
+ secure_vector<byte> RK;
};
extern const u32bit CAST_SBOX1[256];
diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp
index 8be0a8dd6..9476d3faf 100644
--- a/src/block/cast/cast256.cpp
+++ b/src/block/cast/cast256.cpp
@@ -138,40 +138,43 @@ void CAST_256::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void CAST_256::key_schedule(const byte key[], size_t length)
{
- SecureVector<u32bit> K(8);
- for(size_t j = 0; j != length; ++j)
- K[j/4] = (K[j/4] << 8) + key[j];
+ MK.resize(48);
+ RK.resize(48);
+
+ secure_vector<u32bit> K(8);
+ for(size_t i = 0; i != length; ++i)
+ K[i/4] = (K[i/4] << 8) + key[i];
u32bit A = K[0], B = K[1], C = K[2], D = K[3],
E = K[4], F = K[5], G = K[6], H = K[7];
- for(size_t j = 0; j != 48; j += 4)
+ for(size_t i = 0; i != 48; i += 4)
{
- round1(G, H, KEY_MASK[4*j+ 0], KEY_ROT[(4*j+ 0) % 32]);
- round2(F, G, KEY_MASK[4*j+ 1], KEY_ROT[(4*j+ 1) % 32]);
- round3(E, F, KEY_MASK[4*j+ 2], KEY_ROT[(4*j+ 2) % 32]);
- round1(D, E, KEY_MASK[4*j+ 3], KEY_ROT[(4*j+ 3) % 32]);
- round2(C, D, KEY_MASK[4*j+ 4], KEY_ROT[(4*j+ 4) % 32]);
- round3(B, C, KEY_MASK[4*j+ 5], KEY_ROT[(4*j+ 5) % 32]);
- round1(A, B, KEY_MASK[4*j+ 6], KEY_ROT[(4*j+ 6) % 32]);
- round2(H, A, KEY_MASK[4*j+ 7], KEY_ROT[(4*j+ 7) % 32]);
- round1(G, H, KEY_MASK[4*j+ 8], KEY_ROT[(4*j+ 8) % 32]);
- round2(F, G, KEY_MASK[4*j+ 9], KEY_ROT[(4*j+ 9) % 32]);
- round3(E, F, KEY_MASK[4*j+10], KEY_ROT[(4*j+10) % 32]);
- round1(D, E, KEY_MASK[4*j+11], KEY_ROT[(4*j+11) % 32]);
- round2(C, D, KEY_MASK[4*j+12], KEY_ROT[(4*j+12) % 32]);
- round3(B, C, KEY_MASK[4*j+13], KEY_ROT[(4*j+13) % 32]);
- round1(A, B, KEY_MASK[4*j+14], KEY_ROT[(4*j+14) % 32]);
- round2(H, A, KEY_MASK[4*j+15], KEY_ROT[(4*j+15) % 32]);
-
- RK[j ] = (A % 32);
- RK[j+1] = (C % 32);
- RK[j+2] = (E % 32);
- RK[j+3] = (G % 32);
- MK[j ] = H;
- MK[j+1] = F;
- MK[j+2] = D;
- MK[j+3] = B;
+ round1(G, H, KEY_MASK[4*i+ 0], KEY_ROT[(4*i+ 0) % 32]);
+ round2(F, G, KEY_MASK[4*i+ 1], KEY_ROT[(4*i+ 1) % 32]);
+ round3(E, F, KEY_MASK[4*i+ 2], KEY_ROT[(4*i+ 2) % 32]);
+ round1(D, E, KEY_MASK[4*i+ 3], KEY_ROT[(4*i+ 3) % 32]);
+ round2(C, D, KEY_MASK[4*i+ 4], KEY_ROT[(4*i+ 4) % 32]);
+ round3(B, C, KEY_MASK[4*i+ 5], KEY_ROT[(4*i+ 5) % 32]);
+ round1(A, B, KEY_MASK[4*i+ 6], KEY_ROT[(4*i+ 6) % 32]);
+ round2(H, A, KEY_MASK[4*i+ 7], KEY_ROT[(4*i+ 7) % 32]);
+ round1(G, H, KEY_MASK[4*i+ 8], KEY_ROT[(4*i+ 8) % 32]);
+ round2(F, G, KEY_MASK[4*i+ 9], KEY_ROT[(4*i+ 9) % 32]);
+ round3(E, F, KEY_MASK[4*i+10], KEY_ROT[(4*i+10) % 32]);
+ round1(D, E, KEY_MASK[4*i+11], KEY_ROT[(4*i+11) % 32]);
+ round2(C, D, KEY_MASK[4*i+12], KEY_ROT[(4*i+12) % 32]);
+ round3(B, C, KEY_MASK[4*i+13], KEY_ROT[(4*i+13) % 32]);
+ round1(A, B, KEY_MASK[4*i+14], KEY_ROT[(4*i+14) % 32]);
+ round2(H, A, KEY_MASK[4*i+15], KEY_ROT[(4*i+15) % 32]);
+
+ RK[i ] = (A % 32);
+ RK[i+1] = (C % 32);
+ RK[i+2] = (E % 32);
+ RK[i+3] = (G % 32);
+ MK[i ] = H;
+ MK[i+1] = F;
+ MK[i+2] = D;
+ MK[i+3] = B;
}
}
diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h
index 2f2beef47..4f31f187d 100644
--- a/src/block/cast/cast256.h
+++ b/src/block/cast/cast256.h
@@ -21,19 +21,17 @@ class BOTAN_DLL CAST_256 : public Block_Cipher_Fixed_Params<16, 4, 32, 4>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(MK); zeroise(RK); }
+ void clear() { MK.clear(); RK.clear(); }
std::string name() const { return "CAST-256"; }
BlockCipher* clone() const { return new CAST_256; }
-
- CAST_256() : MK(48), RK(48) {}
private:
void key_schedule(const byte[], size_t);
static const u32bit KEY_MASK[192];
static const byte KEY_ROT[32];
- SecureVector<u32bit> MK;
- SecureVector<byte> RK;
+ secure_vector<u32bit> MK;
+ secure_vector<byte> RK;
};
extern const u32bit CAST_SBOX1[256];
diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp
index c500e9bab..2f0a3635d 100644
--- a/src/block/des/des.cpp
+++ b/src/block/des/des.cpp
@@ -206,6 +206,7 @@ void DES::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void DES::key_schedule(const byte key[], size_t)
{
+ round_key.resize(32);
des_key_schedule(&round_key[0], key);
}
@@ -280,6 +281,7 @@ void TripleDES::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void TripleDES::key_schedule(const byte key[], size_t length)
{
+ round_key.resize(3*32);
des_key_schedule(&round_key[0], key);
des_key_schedule(&round_key[32], key + 8);
diff --git a/src/block/des/des.h b/src/block/des/des.h
index db5a375e0..fc42cfee5 100644
--- a/src/block/des/des.h
+++ b/src/block/des/des.h
@@ -21,15 +21,13 @@ class BOTAN_DLL DES : public Block_Cipher_Fixed_Params<8, 8>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(round_key); }
+ void clear() { round_key.clear(); }
std::string name() const { return "DES"; }
BlockCipher* clone() const { return new DES; }
-
- DES() : round_key(32) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> round_key;
+ secure_vector<u32bit> round_key;
};
/**
@@ -41,7 +39,7 @@ class BOTAN_DLL TripleDES : public Block_Cipher_Fixed_Params<8, 16, 24, 8>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(round_key); }
+ void clear() { round_key.clear(); }
std::string name() const { return "TripleDES"; }
BlockCipher* clone() const { return new TripleDES; }
@@ -49,7 +47,7 @@ class BOTAN_DLL TripleDES : public Block_Cipher_Fixed_Params<8, 16, 24, 8>
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> round_key;
+ secure_vector<u32bit> round_key;
};
/*
diff --git a/src/block/des/desx.cpp b/src/block/des/desx.cpp
index b92011e56..7f68e406a 100644
--- a/src/block/des/desx.cpp
+++ b/src/block/des/desx.cpp
@@ -47,9 +47,9 @@ void DESX::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void DESX::key_schedule(const byte key[], size_t)
{
- K1.copy(key, 8);
+ K1.assign(key, key + 8);
des.set_key(key + 8, 8);
- K2.copy(key + 16, 8);
+ K2.assign(key + 16, key + 24);
}
}
diff --git a/src/block/des/desx.h b/src/block/des/desx.h
index 993eca86b..4ff41328f 100644
--- a/src/block/des/desx.h
+++ b/src/block/des/desx.h
@@ -21,14 +21,12 @@ class BOTAN_DLL DESX : public Block_Cipher_Fixed_Params<8, 24>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { des.clear(); zeroise(K1); zeroise(K2); }
+ void clear() { des.clear(); K1.clear(); K2.clear(); }
std::string name() const { return "DESX"; }
BlockCipher* clone() const { return new DESX; }
-
- DESX() : K1(8), K2(8) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<byte> K1, K2;
+ secure_vector<byte> K1, K2;
DES des;
};
diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp
index d4a9faa40..db144a81f 100644
--- a/src/block/gost_28147/gost_28147.cpp
+++ b/src/block/gost_28147/gost_28147.cpp
@@ -51,8 +51,7 @@ GOST_28147_89_Params::GOST_28147_89_Params(const std::string& n) : name(n)
/*
* GOST Constructor
*/
-GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) :
- SBOX(1024), EK(8)
+GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : SBOX(1024)
{
// Convert the parallel 4x4 sboxes into larger word-based sboxes
for(size_t i = 0; i != 4; ++i)
@@ -165,6 +164,7 @@ void GOST_28147_89::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void GOST_28147_89::key_schedule(const byte key[], size_t)
{
+ EK.resize(8);
for(size_t i = 0; i != 8; ++i)
EK[i] = load_le<u32bit>(key, i);
}
diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h
index bc26da774..7c77fea06 100644
--- a/src/block/gost_28147/gost_28147.h
+++ b/src/block/gost_28147/gost_28147.h
@@ -55,7 +55,7 @@ class BOTAN_DLL GOST_28147_89 : public Block_Cipher_Fixed_Params<8, 32>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); }
+ void clear() { EK.clear(); }
std::string name() const;
BlockCipher* clone() const { return new GOST_28147_89(SBOX); }
@@ -65,13 +65,18 @@ class BOTAN_DLL GOST_28147_89 : public Block_Cipher_Fixed_Params<8, 32>
*/
GOST_28147_89(const GOST_28147_89_Params& params);
private:
- GOST_28147_89(const SecureVector<u32bit>& other_SBOX) :
+ GOST_28147_89(const std::vector<u32bit>& other_SBOX) :
SBOX(other_SBOX), EK(8) {}
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> SBOX;
- SecureVector<u32bit> EK;
+ /*
+ * The sbox is not secret, this is just a larger expansion of it
+ * which we generate at runtime for faster execution
+ */
+ std::vector<u32bit> SBOX;
+
+ secure_vector<u32bit> EK;
};
}
diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp
index f9b6cc874..15062abdf 100644
--- a/src/block/idea/idea.cpp
+++ b/src/block/idea/idea.cpp
@@ -124,6 +124,9 @@ void IDEA::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void IDEA::key_schedule(const byte key[], size_t)
{
+ EK.resize(52);
+ DK.resize(52);
+
for(size_t i = 0; i != 8; ++i)
EK[i] = load_be<u16bit>(key, i);
diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h
index 42fa60c47..03ecb1f03 100644
--- a/src/block/idea/idea.h
+++ b/src/block/idea/idea.h
@@ -21,25 +21,24 @@ class BOTAN_DLL IDEA : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); zeroise(DK); }
+ void clear() { EK.clear(); DK.clear(); }
std::string name() const { return "IDEA"; }
BlockCipher* clone() const { return new IDEA; }
-
- IDEA() : EK(52), DK(52) {}
protected:
/**
* @return const reference to encryption subkeys
*/
- const SecureVector<u16bit>& get_EK() const { return EK; }
+ const secure_vector<u16bit>& get_EK() const { return EK; }
/**
* @return const reference to decryption subkeys
*/
- const SecureVector<u16bit>& get_DK() const { return DK; }
+ const secure_vector<u16bit>& get_DK() const { return DK; }
private:
void key_schedule(const byte[], size_t);
- SecureVector<u16bit> EK, DK;
+
+ secure_vector<u16bit> EK, DK;
};
}
diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp
index a57c0396a..ae21338c6 100644
--- a/src/block/kasumi/kasumi.cpp
+++ b/src/block/kasumi/kasumi.cpp
@@ -204,13 +204,15 @@ void KASUMI::key_schedule(const byte key[], size_t)
static const u16bit RC[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF,
0xFEDC, 0xBA98, 0x7654, 0x3210 };
- SecureVector<u16bit> K(16);
+ secure_vector<u16bit> K(16);
for(size_t i = 0; i != 8; ++i)
{
K[i] = load_be<u16bit>(key, i);
K[i+8] = K[i] ^ RC[i];
}
+ EK.resize(64);
+
for(size_t i = 0; i != 8; ++i)
{
EK[8*i ] = rotate_left(K[(i+0) % 8 ], 2);
diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h
index 7871aa170..571085612 100644
--- a/src/block/kasumi/kasumi.h
+++ b/src/block/kasumi/kasumi.h
@@ -21,15 +21,13 @@ class BOTAN_DLL KASUMI : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); }
+ void clear() { EK.clear(); }
std::string name() const { return "KASUMI"; }
BlockCipher* clone() const { return new KASUMI; }
-
- KASUMI() : EK(64) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u16bit> EK;
+ secure_vector<u16bit> EK;
};
}
diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp
index 46308e428..9026f194a 100644
--- a/src/block/lion/lion.cpp
+++ b/src/block/lion/lion.cpp
@@ -16,7 +16,7 @@ namespace Botan {
*/
void Lion::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- SecureVector<byte> buffer_vec(LEFT_SIZE);
+ secure_vector<byte> buffer_vec(LEFT_SIZE);
byte* buffer = &buffer_vec[0];
for(size_t i = 0; i != blocks; ++i)
@@ -43,7 +43,7 @@ void Lion::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Lion::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- SecureVector<byte> buffer_vec(LEFT_SIZE);
+ secure_vector<byte> buffer_vec(LEFT_SIZE);
byte* buffer = &buffer_vec[0];
for(size_t i = 0; i != blocks; ++i)
@@ -72,8 +72,8 @@ void Lion::key_schedule(const byte key[], size_t length)
{
clear();
- key1.copy(key, length / 2);
- key2.copy(key + length / 2, length / 2);
+ key1.assign(key, key + (length / 2));
+ key2.assign(key + (length / 2), key + length);
}
/*
@@ -83,7 +83,7 @@ std::string Lion::name() const
{
return "Lion(" + hash->name() + "," +
cipher->name() + "," +
- to_string(BLOCK_SIZE) + ")";
+ std::to_string(BLOCK_SIZE) + ")";
}
/*
@@ -99,10 +99,10 @@ BlockCipher* Lion::clone() const
*/
void Lion::clear()
{
+ key1.clear();
+ key2.clear();
hash->clear();
cipher->clear();
- zeroise(key1);
- zeroise(key2);
}
/*
diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h
index 5076f4461..d016c0e82 100644
--- a/src/block/lion/lion.h
+++ b/src/block/lion/lion.h
@@ -56,7 +56,7 @@ class BOTAN_DLL Lion : public BlockCipher
HashFunction* hash;
StreamCipher* cipher;
- SecureVector<byte> key1, key2;
+ secure_vector<byte> key1, key2;
};
}
diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp
index ef4a11e9d..77f2a7542 100644
--- a/src/block/lubyrack/lubyrack.cpp
+++ b/src/block/lubyrack/lubyrack.cpp
@@ -17,7 +17,7 @@ void LubyRackoff::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
const size_t len = hash->output_length();
- SecureVector<byte> buffer_vec(len);
+ secure_vector<byte> buffer_vec(len);
byte* buffer = &buffer_vec[0];
for(size_t i = 0; i != blocks; ++i)
@@ -54,7 +54,7 @@ void LubyRackoff::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
const size_t len = hash->output_length();
- SecureVector<byte> buffer_vec(len);
+ secure_vector<byte> buffer_vec(len);
byte* buffer = &buffer_vec[0];
for(size_t i = 0; i != blocks; ++i)
@@ -89,10 +89,8 @@ void LubyRackoff::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void LubyRackoff::key_schedule(const byte key[], size_t length)
{
- K1.resize(length / 2);
- K2.resize(length / 2);
- copy_mem(&K1[0], key , length / 2);
- copy_mem(&K2[0], key + length / 2, length / 2);
+ K1.assign(key, key + (length / 2));
+ K2.assign(key + (length / 2), key + length);
}
/*
@@ -100,8 +98,8 @@ void LubyRackoff::key_schedule(const byte key[], size_t length)
*/
void LubyRackoff::clear()
{
- zeroise(K1);
- zeroise(K2);
+ K1.clear();
+ K2.clear();
hash->clear();
}
diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h
index 81dddf579..e28c60be7 100644
--- a/src/block/lubyrack/lubyrack.h
+++ b/src/block/lubyrack/lubyrack.h
@@ -42,7 +42,7 @@ class BOTAN_DLL LubyRackoff : public BlockCipher
void key_schedule(const byte[], size_t);
HashFunction* hash;
- SecureVector<byte> K1, K2;
+ secure_vector<byte> K1, K2;
};
}
diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp
index 171ce2945..5badc40cc 100644
--- a/src/block/mars/mars.cpp
+++ b/src/block/mars/mars.cpp
@@ -320,12 +320,14 @@ void MARS::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void MARS::key_schedule(const byte key[], size_t length)
{
- SecureVector<u32bit> T(15);
+ secure_vector<u32bit> T(15);
for(size_t i = 0; i != length / 4; ++i)
T[i] = load_le<u32bit>(key, i);
T[length / 4] = static_cast<u32bit>(length) / 4;
+ EK.resize(40);
+
for(u32bit i = 0; i != 4; ++i)
{
T[ 0] ^= rotate_left(T[ 8] ^ T[13], 3) ^ (i );
diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h
index 5ca05f886..488ea1b83 100644
--- a/src/block/mars/mars.h
+++ b/src/block/mars/mars.h
@@ -21,15 +21,13 @@ class BOTAN_DLL MARS : public Block_Cipher_Fixed_Params<16, 16, 32, 4>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); }
+ void clear() { EK.clear(); }
std::string name() const { return "MARS"; }
BlockCipher* clone() const { return new MARS; }
-
- MARS() : EK(40) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK;
+ secure_vector<u32bit> EK;
};
}
diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp
index 36c25a814..97f1e0341 100644
--- a/src/block/misty1/misty1.cpp
+++ b/src/block/misty1/misty1.cpp
@@ -204,7 +204,7 @@ void MISTY1::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void MISTY1::key_schedule(const byte key[], size_t length)
{
- SecureVector<u16bit> KS(32);
+ secure_vector<u16bit> KS(32);
for(size_t i = 0; i != length / 2; ++i)
KS[i] = load_be<u16bit>(key, i);
@@ -241,6 +241,9 @@ void MISTY1::key_schedule(const byte key[], size_t length)
0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04,
0x04, 0x0A, 0x0E, 0x00 };
+ EK.resize(100);
+ DK.resize(100);
+
for(size_t i = 0; i != 100; ++i)
{
EK[i] = KS[EK_ORDER[i]];
@@ -251,11 +254,11 @@ void MISTY1::key_schedule(const byte key[], size_t length)
/*
* MISTY1 Constructor
*/
-MISTY1::MISTY1(size_t rounds) : EK(100), DK(100)
+MISTY1::MISTY1(size_t rounds)
{
if(rounds != 8)
throw Invalid_Argument("MISTY1: Invalid number of rounds: "
- + to_string(rounds));
+ + std::to_string(rounds));
}
}
diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h
index 14d8a2958..81324a0b2 100644
--- a/src/block/misty1/misty1.h
+++ b/src/block/misty1/misty1.h
@@ -21,7 +21,7 @@ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); zeroise(DK); }
+ void clear() { EK.clear(); DK.clear(); }
std::string name() const { return "MISTY1"; }
BlockCipher* clone() const { return new MISTY1; }
@@ -33,7 +33,7 @@ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16>
private:
void key_schedule(const byte[], size_t);
- SecureVector<u16bit> EK, DK;
+ secure_vector<u16bit> EK, DK;
};
}
diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp
index 06c415be9..3929d57d1 100644
--- a/src/block/noekeon/noekeon.cpp
+++ b/src/block/noekeon/noekeon.cpp
@@ -185,6 +185,7 @@ void Noekeon::key_schedule(const byte key[], size_t)
A0 ^= RC[16];
+ DK.resize(4);
DK[0] = A0;
DK[1] = A1;
DK[2] = A2;
@@ -192,6 +193,7 @@ void Noekeon::key_schedule(const byte key[], size_t)
theta(A0, A1, A2, A3);
+ EK.resize(4);
EK[0] = A0;
EK[1] = A1;
EK[2] = A2;
@@ -203,8 +205,8 @@ void Noekeon::key_schedule(const byte key[], size_t)
*/
void Noekeon::clear()
{
- zeroise(EK);
- zeroise(DK);
+ EK.clear();
+ DK.clear();
}
}
diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h
index 7c5c73dcb..108b34cd6 100644
--- a/src/block/noekeon/noekeon.h
+++ b/src/block/noekeon/noekeon.h
@@ -24,8 +24,6 @@ class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16>
void clear();
std::string name() const { return "Noekeon"; }
BlockCipher* clone() const { return new Noekeon; }
-
- Noekeon() : EK(4), DK(4) {}
protected:
/**
* The Noekeon round constants
@@ -35,16 +33,16 @@ class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16>
/**
* @return const reference to encryption subkeys
*/
- const SecureVector<u32bit>& get_EK() const { return EK; }
+ const secure_vector<u32bit>& get_EK() const { return EK; }
/**
* @return const reference to decryption subkeys
*/
- const SecureVector<u32bit>& get_DK() const { return DK; }
+ const secure_vector<u32bit>& get_DK() const { return DK; }
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK, DK;
+ secure_vector<u32bit> EK, DK;
};
}
diff --git a/src/block/noekeon_simd/noekeon_simd.cpp b/src/block/noekeon_simd/noekeon_simd.cpp
index b2beafc82..2a4c1fd74 100644
--- a/src/block/noekeon_simd/noekeon_simd.cpp
+++ b/src/block/noekeon_simd/noekeon_simd.cpp
@@ -65,7 +65,7 @@ namespace Botan {
*/
void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const SecureVector<u32bit>& EK = this->get_EK();
+ const secure_vector<u32bit>& EK = this->get_EK();
SIMD_32 K0 = SIMD_32(EK[0]);
SIMD_32 K1 = SIMD_32(EK[1]);
@@ -122,7 +122,7 @@ void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const SecureVector<u32bit>& DK = this->get_DK();
+ const secure_vector<u32bit>& DK = this->get_DK();
SIMD_32 K0 = SIMD_32(DK[0]);
SIMD_32 K1 = SIMD_32(DK[1]);
diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp
index 97ca5d577..548c2f095 100644
--- a/src/block/rc2/rc2.cpp
+++ b/src/block/rc2/rc2.cpp
@@ -124,8 +124,8 @@ void RC2::key_schedule(const byte key[], size_t length)
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68,
0xFE, 0x7F, 0xC1, 0xAD };
- SecureVector<byte> L(128);
- L.copy(key, length);
+ secure_vector<byte> L(128);
+ copy_mem(&L[0], key, length);
for(size_t i = length; i != 128; ++i)
L[i] = TABLE[(L[i-1] + L[i-length]) % 256];
@@ -135,6 +135,7 @@ void RC2::key_schedule(const byte key[], size_t length)
for(s32bit i = 127-length; i >= 0; --i)
L[i] = TABLE[L[i+1] ^ L[i+length]];
+ K.resize(64);
load_le<u16bit>(&K[0], &L[0], 64);
}
diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h
index 1ebad1e73..223c48792 100644
--- a/src/block/rc2/rc2.h
+++ b/src/block/rc2/rc2.h
@@ -28,15 +28,13 @@ class BOTAN_DLL RC2 : public Block_Cipher_Fixed_Params<8, 1, 32>
*/
static byte EKB_code(size_t bits);
- void clear() { zeroise(K); }
+ void clear() { K.clear(); }
std::string name() const { return "RC2"; }
BlockCipher* clone() const { return new RC2; }
-
- RC2() : K(64) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u16bit> K;
+ secure_vector<u16bit> K;
};
}
diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp
index cfcc4cb64..fe558076a 100644
--- a/src/block/rc5/rc5.cpp
+++ b/src/block/rc5/rc5.cpp
@@ -18,8 +18,6 @@ namespace Botan {
*/
void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const size_t rounds = (S.size() - 2) / 2;
-
for(size_t i = 0; i != blocks; ++i)
{
u32bit A = load_le<u32bit>(in, 0);
@@ -53,8 +51,6 @@ void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const size_t rounds = (S.size() - 2) / 2;
-
for(size_t i = 0; i != blocks; ++i)
{
u32bit A = load_le<u32bit>(in, 0);
@@ -88,6 +84,8 @@ void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void RC5::key_schedule(const byte key[], size_t length)
{
+ S.resize(2*rounds + 2);
+
const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1);
const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size());
@@ -95,7 +93,7 @@ void RC5::key_schedule(const byte key[], size_t length)
for(size_t i = 1; i != S.size(); ++i)
S[i] = S[i-1] + 0x9E3779B9;
- SecureVector<u32bit> K(8);
+ secure_vector<u32bit> K(8);
for(s32bit i = length-1; i >= 0; --i)
K[i/4] = (K[i/4] << 8) + key[i];
@@ -116,19 +114,17 @@ void RC5::key_schedule(const byte key[], size_t length)
*/
std::string RC5::name() const
{
- return "RC5(" + to_string(get_rounds()) + ")";
+ return "RC5(" + std::to_string(rounds) + ")";
}
/*
* RC5 Constructor
*/
-RC5::RC5(size_t rounds)
+RC5::RC5(size_t r) : rounds(r)
{
if(rounds < 8 || rounds > 32 || (rounds % 4 != 0))
throw Invalid_Argument("RC5: Invalid number of rounds " +
- to_string(rounds));
-
- S.resize(2*rounds + 2);
+ std::to_string(rounds));
}
}
diff --git a/src/block/rc5/rc5.h b/src/block/rc5/rc5.h
index c69705471..2279260a3 100644
--- a/src/block/rc5/rc5.h
+++ b/src/block/rc5/rc5.h
@@ -21,9 +21,9 @@ class BOTAN_DLL RC5 : public Block_Cipher_Fixed_Params<8, 1, 32>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(S); }
+ void clear() { S.clear(); }
std::string name() const;
- BlockCipher* clone() const { return new RC5(get_rounds()); }
+ BlockCipher* clone() const { return new RC5(rounds); }
/**
* @param rounds the number of RC5 rounds to run. Must be between
@@ -31,11 +31,10 @@ class BOTAN_DLL RC5 : public Block_Cipher_Fixed_Params<8, 1, 32>
*/
RC5(size_t rounds);
private:
- size_t get_rounds() const { return (S.size() - 2) / 2; }
-
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> S;
+ size_t rounds;
+ secure_vector<u32bit> S;
};
}
diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp
index 53ca5a7a2..5a6c1091d 100644
--- a/src/block/rc6/rc6.cpp
+++ b/src/block/rc6/rc6.cpp
@@ -113,6 +113,8 @@ void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void RC6::key_schedule(const byte key[], size_t length)
{
+ S.resize(44);
+
const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1);
const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size());
@@ -120,7 +122,7 @@ void RC6::key_schedule(const byte key[], size_t length)
for(size_t i = 1; i != S.size(); ++i)
S[i] = S[i-1] + 0x9E3779B9;
- SecureVector<u32bit> K(8);
+ secure_vector<u32bit> K(8);
for(s32bit i = length-1; i >= 0; --i)
K[i/4] = (K[i/4] << 8) + key[i];
diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h
index af7b62316..e30a267e6 100644
--- a/src/block/rc6/rc6.h
+++ b/src/block/rc6/rc6.h
@@ -21,15 +21,13 @@ class BOTAN_DLL RC6 : public Block_Cipher_Fixed_Params<16, 1, 32>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(S); }
+ void clear() { S.clear(); }
std::string name() const { return "RC6"; }
BlockCipher* clone() const { return new RC6; }
-
- RC6() : S(44) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> S;
+ secure_vector<u32bit> S;
};
}
diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp
index a3a6cefd8..1b79b3c2c 100644
--- a/src/block/safer/safer_sk.cpp
+++ b/src/block/safer/safer_sk.cpp
@@ -90,8 +90,6 @@ const byte LOG[512] = {
*/
void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const size_t rounds = get_rounds();
-
for(size_t i = 0; i != blocks; ++i)
{
byte A = in[0], B = in[1], C = in[2], D = in[3],
@@ -128,8 +126,6 @@ void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void SAFER_SK::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const size_t rounds = get_rounds();
-
for(size_t i = 0; i != blocks; ++i)
{
byte A = in[0], B = in[1], C = in[2], D = in[3],
@@ -208,7 +204,9 @@ void SAFER_SK::key_schedule(const byte key[], size_t)
0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F };
- SecureVector<byte> KB(18);
+ EK.resize(16 * rounds + 8);
+
+ secure_vector<byte> KB(18);
for(size_t i = 0; i != 8; ++i)
{
@@ -216,7 +214,7 @@ void SAFER_SK::key_schedule(const byte key[], size_t)
KB[17] ^= KB[i+9] = EK[i] = key[i+8];
}
- for(size_t i = 0; i != get_rounds(); ++i)
+ for(size_t i = 0; i != rounds; ++i)
{
for(size_t j = 0; j != 18; ++j)
KB[j] = rotate_left(KB[j], 6);
@@ -230,7 +228,7 @@ void SAFER_SK::key_schedule(const byte key[], size_t)
*/
std::string SAFER_SK::name() const
{
- return "SAFER-SK(" + to_string(get_rounds()) + ")";
+ return "SAFER-SK(" + std::to_string(rounds) + ")";
}
/*
@@ -238,18 +236,16 @@ std::string SAFER_SK::name() const
*/
BlockCipher* SAFER_SK::clone() const
{
- return new SAFER_SK(get_rounds());
+ return new SAFER_SK(rounds);
}
/*
* SAFER-SK Constructor
*/
-SAFER_SK::SAFER_SK(size_t rounds)
+SAFER_SK::SAFER_SK(size_t r) : rounds(r)
{
if(rounds > 13 || rounds == 0)
throw Invalid_Argument(name() + ": Invalid number of rounds");
-
- EK.resize(16 * rounds + 8);
}
}
diff --git a/src/block/safer/safer_sk.h b/src/block/safer/safer_sk.h
index 564ea5c50..dfe226652 100644
--- a/src/block/safer/safer_sk.h
+++ b/src/block/safer/safer_sk.h
@@ -21,7 +21,7 @@ class BOTAN_DLL SAFER_SK : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); }
+ void clear() { EK.clear(); }
std::string name() const;
BlockCipher* clone() const;
@@ -31,10 +31,10 @@ class BOTAN_DLL SAFER_SK : public Block_Cipher_Fixed_Params<8, 16>
*/
SAFER_SK(size_t rounds);
private:
- size_t get_rounds() const { return (EK.size() - 8) / 16; }
void key_schedule(const byte[], size_t);
- SecureVector<byte> EK;
+ size_t rounds;
+ secure_vector<byte> EK;
};
}
diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp
index 408220013..fb8708214 100644
--- a/src/block/seed/seed.cpp
+++ b/src/block/seed/seed.cpp
@@ -111,13 +111,15 @@ void SEED::key_schedule(const byte key[], size_t)
0x779B99E3, 0xEF3733C6, 0xDE6E678D, 0xBCDCCF1B
};
- SecureVector<u32bit> WK(4);
+ secure_vector<u32bit> WK(4);
for(size_t i = 0; i != 4; ++i)
WK[i] = load_be<u32bit>(key, i);
G_FUNC G;
+ K.resize(32);
+
for(size_t i = 0; i != 16; i += 2)
{
K[2*i ] = G(WK[0] + WK[2] - RC[i]);
diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h
index 979312930..95dab758d 100644
--- a/src/block/seed/seed.h
+++ b/src/block/seed/seed.h
@@ -21,11 +21,9 @@ class BOTAN_DLL SEED : public Block_Cipher_Fixed_Params<16, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(K); }
+ void clear() { K.clear(); }
std::string name() const { return "SEED"; }
BlockCipher* clone() const { return new SEED; }
-
- SEED() : K(32) {}
private:
void key_schedule(const byte[], size_t);
@@ -37,7 +35,7 @@ class BOTAN_DLL SEED : public Block_Cipher_Fixed_Params<16, 16>
static const u32bit S0[256], S1[256], S2[256], S3[256];
};
- SecureVector<u32bit> K;
+ secure_vector<u32bit> K;
};
}
diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp
index b3cf0f6c9..0f0a4fd63 100644
--- a/src/block/serpent/serpent.cpp
+++ b/src/block/serpent/serpent.cpp
@@ -358,7 +358,7 @@ void Serpent::key_schedule(const byte key[], size_t length)
{
const u32bit PHI = 0x9E3779B9;
- SecureVector<u32bit> W(140);
+ secure_vector<u32bit> W(140);
for(size_t i = 0; i != length / 4; ++i)
W[i] = load_le<u32bit>(key, i);
@@ -387,7 +387,8 @@ void Serpent::key_schedule(const byte key[], size_t length)
SBoxE8(W[120],W[121],W[122],W[123]); SBoxE7(W[124],W[125],W[126],W[127]);
SBoxE6(W[128],W[129],W[130],W[131]); SBoxE5(W[132],W[133],W[134],W[135]);
SBoxE4(W[136],W[137],W[138],W[139]);
- round_key.copy(&W[8], 132);
+
+ round_key.assign(&W[8], &W[140]);
}
}
diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h
index df3f039aa..9e5abcf35 100644
--- a/src/block/serpent/serpent.h
+++ b/src/block/serpent/serpent.h
@@ -21,17 +21,15 @@ class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(round_key); }
+ void clear() { round_key.clear(); }
std::string name() const { return "Serpent"; }
BlockCipher* clone() const { return new Serpent; }
-
- Serpent() : round_key(132) {}
protected:
/**
* For use by subclasses using SIMD, asm, etc
* @return const reference to the key schedule
*/
- const SecureVector<u32bit>& get_round_keys() const
+ const secure_vector<u32bit>& get_round_keys() const
{ return round_key; }
/**
@@ -45,7 +43,7 @@ class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
private:
void key_schedule(const byte key[], size_t length);
- SecureVector<u32bit> round_key;
+ secure_vector<u32bit> round_key;
};
}
diff --git a/src/block/serpent_x86_32/serp_x86_32.cpp b/src/block/serpent_x86_32/serp_x86_32.cpp
index 4cefe1d65..9566ed8a6 100644
--- a/src/block/serpent_x86_32/serp_x86_32.cpp
+++ b/src/block/serpent_x86_32/serp_x86_32.cpp
@@ -72,7 +72,7 @@ void Serpent_X86_32::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Serpent_X86_32::key_schedule(const byte key[], size_t length)
{
- SecureVector<u32bit> W(140);
+ secure_vector<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);
diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp
index b73972b59..fb9916092 100644
--- a/src/block/skipjack/skipjack.cpp
+++ b/src/block/skipjack/skipjack.cpp
@@ -183,6 +183,7 @@ void Skipjack::key_schedule(const byte key[], size_t)
0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3, 0xBD, 0xA8, 0x3A, 0x01,
0x05, 0x59, 0x2A, 0x46 };
+ FTAB.resize(256*10);
for(size_t i = 0; i != 10; ++i)
for(size_t j = 0; j != 256; ++j)
FTAB[256*i+j] = F[j ^ key[9-i]];
@@ -193,7 +194,7 @@ void Skipjack::key_schedule(const byte key[], size_t)
*/
void Skipjack::clear()
{
- zeroise(FTAB);
+ FTAB.clear();
}
}
diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h
index 051d35351..60a55c8a5 100644
--- a/src/block/skipjack/skipjack.h
+++ b/src/block/skipjack/skipjack.h
@@ -24,12 +24,10 @@ class BOTAN_DLL Skipjack : public Block_Cipher_Fixed_Params<8, 10>
void clear();
std::string name() const { return "Skipjack"; }
BlockCipher* clone() const { return new Skipjack; }
-
- Skipjack() : FTAB(2560) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<byte> FTAB;
+ secure_vector<byte> FTAB;
};
}
diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp
index cd1865582..c319dab16 100644
--- a/src/block/square/square.cpp
+++ b/src/block/square/square.cpp
@@ -142,7 +142,7 @@ void Square::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Square::key_schedule(const byte key[], size_t)
{
- SecureVector<u32bit> XEK(36), XDK(36);
+ secure_vector<u32bit> XEK(36), XDK(36);
for(size_t i = 0; i != 4; ++i)
XEK[i] = load_be<u32bit>(key, i);
@@ -160,6 +160,12 @@ void Square::key_schedule(const byte key[], size_t)
transform(&XEK[4*i]);
}
+ EK.assign(&XEK[4], &XEK[36]);
+ DK.assign(&XDK[4], &XDK[36]);
+
+ ME.resize(32);
+ MD.resize(32);
+
for(size_t i = 0; i != 4; ++i)
for(size_t j = 0; j != 4; ++j)
{
@@ -168,9 +174,6 @@ void Square::key_schedule(const byte key[], size_t)
MD[4*i+j ] = get_byte(j, XDK[i ]);
MD[4*i+j+16] = get_byte(j, XEK[i ]);
}
-
- EK.copy(&XEK[4], 28);
- DK.copy(&XDK[4], 28);
}
/*
@@ -209,10 +212,10 @@ void Square::transform(u32bit round_key[4])
*/
void Square::clear()
{
- zeroise(EK);
- zeroise(DK);
- zeroise(ME);
- zeroise(MD);
+ EK.clear();
+ DK.clear();
+ ME.clear();
+ MD.clear();
}
}
diff --git a/src/block/square/square.h b/src/block/square/square.h
index 5147c0383..618dbf6d9 100644
--- a/src/block/square/square.h
+++ b/src/block/square/square.h
@@ -24,8 +24,6 @@ class BOTAN_DLL Square : public Block_Cipher_Fixed_Params<16, 16>
void clear();
std::string name() const { return "Square"; }
BlockCipher* clone() const { return new Square; }
-
- Square() : EK(28), DK(28), ME(32), MD(32) {}
private:
void key_schedule(const byte[], size_t);
@@ -45,8 +43,8 @@ class BOTAN_DLL Square : public Block_Cipher_Fixed_Params<16, 16>
static const u32bit TD2[256];
static const u32bit TD3[256];
- SecureVector<u32bit> EK, DK;
- SecureVector<byte> ME, MD;
+ secure_vector<u32bit> EK, DK;
+ secure_vector<byte> ME, MD;
};
}
diff --git a/src/block/tea/tea.cpp b/src/block/tea/tea.cpp
index 4ef995a7c..e45f7cb48 100644
--- a/src/block/tea/tea.cpp
+++ b/src/block/tea/tea.cpp
@@ -65,6 +65,7 @@ void TEA::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void TEA::key_schedule(const byte key[], size_t)
{
+ K.resize(4);
for(size_t i = 0; i != 4; ++i)
K[i] = load_be<u32bit>(key, i);
}
diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h
index 0290b112f..d2f81da17 100644
--- a/src/block/tea/tea.h
+++ b/src/block/tea/tea.h
@@ -21,14 +21,12 @@ class BOTAN_DLL TEA : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(K); }
+ void clear() { K.clear(); }
std::string name() const { return "TEA"; }
BlockCipher* clone() const { return new TEA; }
-
- TEA() : K(4) {}
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> K;
+ secure_vector<u32bit> K;
};
}
diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp
index c0735e202..eb5b279b9 100644
--- a/src/block/twofish/twofish.cpp
+++ b/src/block/twofish/twofish.cpp
@@ -121,7 +121,10 @@ void Twofish::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void Twofish::key_schedule(const byte key[], size_t length)
{
- SecureVector<byte> S(16);
+ SB.resize(1024);
+ RK.resize(40);
+
+ secure_vector<byte> S(16);
for(size_t i = 0; i != length; ++i)
rs_mul(&S[4*(i/8)], key[i], i);
@@ -235,8 +238,8 @@ void Twofish::rs_mul(byte S[4], byte key, size_t offset)
*/
void Twofish::clear()
{
- zeroise(SB);
- zeroise(RK);
+ SB.clear();
+ RK.clear();
}
}
diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h
index 7594bdcfd..3d8e47498 100644
--- a/src/block/twofish/twofish.h
+++ b/src/block/twofish/twofish.h
@@ -24,8 +24,6 @@ class BOTAN_DLL Twofish : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
void clear();
std::string name() const { return "Twofish"; }
BlockCipher* clone() const { return new Twofish; }
-
- Twofish() : SB(1024), RK(40) {}
private:
void key_schedule(const byte[], size_t);
@@ -41,7 +39,7 @@ class BOTAN_DLL Twofish : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
static const byte EXP_TO_POLY[255];
static const byte POLY_TO_EXP[255];
- SecureVector<u32bit> SB, RK;
+ secure_vector<u32bit> SB, RK;
};
}
diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp
index 597eedd07..b0c976b36 100644
--- a/src/block/xtea/xtea.cpp
+++ b/src/block/xtea/xtea.cpp
@@ -123,7 +123,9 @@ void XTEA::decrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void XTEA::key_schedule(const byte key[], size_t)
{
- SecureVector<u32bit> UK(4);
+ EK.resize(64);
+
+ secure_vector<u32bit> UK(4);
for(size_t i = 0; i != 4; ++i)
UK[i] = load_be<u32bit>(key, i);
diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h
index 985e9d6d1..1d86bf5ce 100644
--- a/src/block/xtea/xtea.h
+++ b/src/block/xtea/xtea.h
@@ -21,20 +21,18 @@ class BOTAN_DLL XTEA : public Block_Cipher_Fixed_Params<8, 16>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- void clear() { zeroise(EK); }
+ void clear() { EK.clear(); }
std::string name() const { return "XTEA"; }
BlockCipher* clone() const { return new XTEA; }
-
- XTEA() : EK(64) {}
protected:
/**
* @return const reference to the key schedule
*/
- const SecureVector<u32bit>& get_EK() const { return EK; }
+ const secure_vector<u32bit>& get_EK() const { return EK; }
private:
void key_schedule(const byte[], size_t);
- SecureVector<u32bit> EK;
+ secure_vector<u32bit> EK;
};
}
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index b3e6f8197..4668811bc 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -26,7 +26,7 @@
#endif
/* Chunk sizes */
-#define BOTAN_DEFAULT_BUFFER_SIZE 4096
+#define BOTAN_DEFAULT_BUFFER_SIZE 1024
#define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024
#define BOTAN_BLOCK_CIPHER_PAR_MULT 4
diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt
index e5d52db3d..0a692e9aa 100644
--- a/src/build-data/cc/clang.txt
+++ b/src/build-data/cc/clang.txt
@@ -10,7 +10,7 @@ add_include_dir_option -I
add_lib_dir_option -L
add_lib_option -l
-lang_flags "-D_REENTRANT -ansi -Wno-long-long"
+lang_flags "-D_REENTRANT -std=c++0x"
warning_flags "-W -Wall"
makefile_style unix
@@ -36,18 +36,10 @@ westmere -> "-march=corei7 -maes"
</mach_opt>
<mach_abi_linking>
+all -> "-pthread"
+
x86_64 -> "-m64"
-mips64 -> "-mabi=64"
-s390 -> "-m31"
-s390x -> "-m64"
-sparc32 -> "-m32 -mno-app-regs"
-sparc64 -> "-m64 -mno-app-regs"
ppc64 -> "-m64"
-# This should probably be used on most/all targets, but the docs are incomplete
-openbsd -> "-pthread"
-freebsd -> "-pthread"
-dragonfly -> "-pthread"
-netbsd -> "-pthread -D_NETBSD_SOURCE"
-qnx -> "-fexceptions -D_QNX_SOURCE"
+netbsd -> "-D_NETBSD_SOURCE"
</mach_abi_linking>
diff --git a/src/build-data/cc/compaq.txt b/src/build-data/cc/compaq.txt
deleted file mode 100644
index 7e7f1ea56..000000000
--- a/src/build-data/cc/compaq.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-macro_name COMPAQ
-
-binary_name cxx
-
-compile_option "-c "
-output_to_option "-o "
-add_include_dir_option -I
-add_lib_dir_option -L
-add_lib_option -l
-
-# -O3 and up seem to be unhappy with Botan
-lib_opt_flags "-O2"
-check_opt_flags "-O2"
-debug_flags -g
-no_debug_flags ""
-lang_flags "-std ansi -D__USE_STD_IOSTREAM"
-
-makefile_style unix
-
-<so_link_flags>
-default -> "$(CXX) -shared -soname $(SONAME)"
-</so_link_flags>
-
-<mach_opt>
-alpha -> "-arch=SUBMODEL" alpha-
-</mach_opt>
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index 3de85099c..ccbba33fa 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -1,8 +1,6 @@
macro_name GCC
-binary_name g++
-
-has_tr1 yes
+binary_name g++-4.8.0-r187608
compile_option "-c "
output_to_option "-o "
@@ -10,10 +8,10 @@ add_include_dir_option -I
add_lib_dir_option -L
add_lib_option -l
-lang_flags "-D_REENTRANT -Wno-long-long"
+lang_flags "-D_REENTRANT -std=c++0x"
warning_flags "-W -Wall"
-maintainer_warning_flags "-Werror -Weffc++ -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast"
+maintainer_warning_flags "-Werror -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant"
lib_opt_flags "-O3"
check_opt_flags "-O2"
@@ -90,18 +88,16 @@ x86_64 -> "-march=SUBMODEL -momit-leaf-frame-pointer"
# The 'linking' bit means "use this for both compiling *and* linking"
<mach_abi_linking>
-x86_64 -> "-m64"
+all -> "-pthread"
+
mips64 -> "-mabi=64"
s390 -> "-m31"
s390x -> "-m64"
sparc32 -> "-m32 -mno-app-regs"
sparc64 -> "-m64 -mno-app-regs"
ppc64 -> "-m64"
+x86_64 -> "-m64"
-# This should probably be used on most/all targets, but the docs are unclear
-openbsd -> "-pthread"
-freebsd -> "-pthread"
-dragonfly -> "-pthread"
-netbsd -> "-pthread -D_NETBSD_SOURCE"
-qnx -> "-fexceptions -D_QNX_SOURCE"
+netbsd -> "-D_NETBSD_SOURCE"
+qnx -> "-fexceptions -D_QNX_SOURCE"
</mach_abi_linking>
diff --git a/src/build-data/cc/icc.txt b/src/build-data/cc/icc.txt
index 28c1a2816..e11875cb1 100644
--- a/src/build-data/cc/icc.txt
+++ b/src/build-data/cc/icc.txt
@@ -2,8 +2,6 @@ macro_name INTEL
binary_name icpc
-has_tr1 yes
-
compile_option "-c "
output_to_option "-o "
add_include_dir_option -I
@@ -14,7 +12,7 @@ lib_opt_flags "-O2 -ip -unroll"
check_opt_flags "-O2"
debug_flags -g
no_debug_flags "-fomit-frame-pointer"
-lang_flags ""
+lang_flags "-std=c++0x"
warning_flags "-w1"
shared_flags "-fPIC"
diff --git a/src/build-data/cc/kai.txt b/src/build-data/cc/kai.txt
deleted file mode 100644
index 2d9c0cd65..000000000
--- a/src/build-data/cc/kai.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-macro_name KAI
-
-binary_name KCC
-
-compile_option "-c "
-output_to_option "-o "
-add_include_dir_option -I
-add_lib_dir_option -L
-add_lib_option -l
-
-ar_command "KCC -o"
-
-lib_opt_flags "+K3 --inline_auto_space_time=65 --abstract_pointer"
-check_opt_flags "+K3"
-lang_flags "-D__KAI_STRICT"
-debug_flags -g
-no_debug_flags ""
-
-makefile_style unix
-
-<so_link_flags>
-default -> "$(CXX) --soname $(SONAME)"
-</so_link_flags>
-
-<mach_abi_linking>
-all -> "--one_per"
-</mach_abi_linking>
diff --git a/src/build-data/cc/mipspro.txt b/src/build-data/cc/mipspro.txt
deleted file mode 100644
index 28b47b30d..000000000
--- a/src/build-data/cc/mipspro.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-macro_name MIPSPRO
-
-binary_name CC
-
-compile_option "-c "
-output_to_option "-o "
-add_include_dir_option -I
-add_lib_dir_option -L
-add_lib_option -l
-
-lib_opt_flags "-O3 -OPT:alias=TYPED"
-check_opt_flags "-O3 -OPT:alias=TYPED"
-debug_flags "-g3"
-no_debug_flags ""
-shared_flags "-KPIC"
-lang_flags "-ansi -LANG:ansi-for-init-scope=ON"
-# Disabled, because, while my code is fine, it warns about a lot of it's own
-# headers <g>
-#warning_flags "-fullwarn"
-
-makefile_style unix
-
-<so_link_flags>
-default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
-</so_link_flags>
-
-<mach_opt>
-mips32 -> "-mips1"
-mips64 -> "-mips3"
-
-mips64-r5000 -> "-mips4 -r5000"
-mips64-r8000 -> "-mips4 -r8000"
-mips64-r10000 -> "-mips4 -r10000"
-</mach_opt>
-
-<mach_abi_linking>
-mips32 -> "-n32"
-mips64 -> "-64"
-</mach_abi_linking>
diff --git a/src/build-data/cc/sgipro64.txt b/src/build-data/cc/sgipro64.txt
deleted file mode 100644
index e6a58f16d..000000000
--- a/src/build-data/cc/sgipro64.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-macro_name SGI_PRO64
-
-binary_name sgiCC
-
-compile_option "-c "
-output_to_option "-o "
-add_include_dir_option -I
-add_lib_dir_option -L
-add_lib_option -l
-
-lib_opt_flags "-O3 -OPT:alias=TYPED"
-check_opt_flags "-O3 -OPT:alias=TYPED"
-debug_flags "-g3"
-no_debug_flags ""
-shared_flags "-KPIC"
-lang_flags "-ansi -LANG:ansi-for-init-scope=ON"
-warning_flags "-Wall -W"
-
-makefile_style unix
-
-<so_link_flags>
-default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
-</so_link_flags>
-
-<mach_opt>
-
-</mach_opt>
diff --git a/src/build-data/os/windows.txt b/src/build-data/os/windows.txt
index 2f344e33c..30a6b77f8 100644
--- a/src/build-data/os/windows.txt
+++ b/src/build-data/os/windows.txt
@@ -11,10 +11,11 @@ install_cmd_data "copy"
install_cmd_exec "copy"
<target_features>
-win32_virtual_lock
-win32_get_systemtime
gmtime_s
loadlibrary
+win32_get_systemtime
+win32_query_perf_counter
+win32_virtual_lock
</target_features>
<aliases>
diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp
index db5d2fbaf..a3a4d043d 100644
--- a/src/cert/cvc/asn1_eac_tm.cpp
+++ b/src/cert/cvc/asn1_eac_tm.cpp
@@ -1,7 +1,7 @@
/*
* EAC Time Types
* (C) 2007 FlexSecure GmbH
-* 2008 Jack Lloyd
+* 2008-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -12,17 +12,17 @@
#include <botan/charset.h>
#include <botan/parsing.h>
#include <botan/internal/rounding.h>
-#include <botan/time.h>
+#include <botan/calendar.h>
namespace Botan {
namespace {
-SecureVector<byte> enc_two_digit(u32bit in)
+secure_vector<byte> enc_two_digit(u32bit in)
{
- SecureVector<byte> result;
+ secure_vector<byte> result;
in %= 100;
- if (in < 10)
+ if(in < 10)
result.push_back(0x00);
else
{
@@ -51,9 +51,10 @@ u32bit dec_two_digit(byte b1, byte b2)
/*
* Create an EAC_Time
*/
-EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t) : tag(t)
+EAC_Time::EAC_Time(const std::chrono::system_clock::time_point& time,
+ ASN1_Tag t) : tag(t)
{
- calendar_point cal = calendar_value(timer);
+ calendar_point cal = calendar_value(time);
year = cal.year;
month = cal.month;
@@ -67,6 +68,7 @@ EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : tag(t)
{
set_to(t_spec);
}
+
/*
* Create an EAC_Time
*/
@@ -80,7 +82,7 @@ EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) :
*/
void EAC_Time::set_to(const std::string& time_str)
{
- if (time_str == "")
+ if(time_str == "")
{
year = month = day = 0;
return;
@@ -89,28 +91,28 @@ void EAC_Time::set_to(const std::string& time_str)
std::vector<std::string> params;
std::string current;
- for (u32bit j = 0; j != time_str.size(); ++j)
+ for(u32bit j = 0; j != time_str.size(); ++j)
{
- if (Charset::is_digit(time_str[j]))
+ if(Charset::is_digit(time_str[j]))
current += time_str[j];
else
{
- if (current != "")
+ if(current != "")
params.push_back(current);
current.clear();
}
}
- if (current != "")
+ if(current != "")
params.push_back(current);
- if (params.size() != 3)
+ if(params.size() != 3)
throw Invalid_Argument("Invalid time specification " + time_str);
year = to_u32bit(params[0]);
month = to_u32bit(params[1]);
day = to_u32bit(params[2]);
- if (!passes_sanity_check())
+ if(!passes_sanity_check())
throw Invalid_Argument("Invalid time specification " + time_str);
}
@@ -129,15 +131,10 @@ void EAC_Time::encode_into(DER_Encoder& der) const
*/
std::string EAC_Time::as_string() const
{
- if (time_is_set() == false)
+ if(time_is_set() == false)
throw Invalid_State("EAC_Time::as_string: No time set");
- std::string asn1rep;
- asn1rep = to_string(year, 2);
-
- asn1rep += to_string(month, 2) + to_string(day, 2);
-
- return asn1rep;
+ return std::to_string(year * 10000 + month * 100 + day);
}
/*
@@ -153,15 +150,14 @@ bool EAC_Time::time_is_set() const
*/
std::string EAC_Time::readable_string() const
{
- if (time_is_set() == false)
+ if(time_is_set() == false)
throw Invalid_State("EAC_Time::readable_string: No time set");
- std::string readable;
- readable += to_string(year, 2) + "/";
- readable += to_string(month, 2) + "/";
- readable += to_string(day, 2) + " ";
+ std::string output(11, 0);
- return readable;
+ std::sprintf(&output[0], "%04d/%02d/%02d", year, month, day);
+
+ return output;
}
/*
@@ -169,11 +165,11 @@ std::string EAC_Time::readable_string() const
*/
bool EAC_Time::passes_sanity_check() const
{
- if (year < 2000 || year > 2099)
+ if(year < 2000 || year > 2099)
return false;
- if (month == 0 || month > 12)
+ if(month == 0 || month > 12)
return false;
- if (day == 0 || day > 31)
+ if(day == 0 || day > 31)
return false;
return true;
@@ -182,11 +178,11 @@ bool EAC_Time::passes_sanity_check() const
/*
* modification functions
*/
-
void EAC_Time::add_years(u32bit years)
{
year += years;
}
+
void EAC_Time::add_months(u32bit months)
{
year += months/12;
@@ -198,23 +194,22 @@ void EAC_Time::add_months(u32bit months)
}
}
-
/*
* Compare this time against another
*/
s32bit EAC_Time::cmp(const EAC_Time& other) const
{
- if (time_is_set() == false)
+ if(time_is_set() == false)
throw Invalid_State("EAC_Time::cmp: No time set");
const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
- if (year < other.year) return EARLIER;
- if (year > other.year) return LATER;
- if (month < other.month) return EARLIER;
- if (month > other.month) return LATER;
- if (day < other.day) return EARLIER;
- if (day > other.day) return LATER;
+ if(year < other.year) return EARLIER;
+ if(year > other.year) return LATER;
+ if(month < other.month) return EARLIER;
+ if(month > other.month) return LATER;
+ if(day < other.day) return EARLIER;
+ if(day > other.day) return LATER;
return SAME_TIME;
}
@@ -283,61 +278,16 @@ void EAC_Time::decode_from(BER_Decoder& source)
}
-u32bit EAC_Time::get_year() const
- {
- return year;
- }
-
-u32bit EAC_Time::get_month() const
- {
- return month;
- }
-
-u32bit EAC_Time::get_day() const
- {
- return day;
- }
-
/*
* make the value an octet string for encoding
*/
-SecureVector<byte> EAC_Time::encoded_eac_time() const
+secure_vector<byte> EAC_Time::encoded_eac_time() const
{
- SecureVector<byte> result;
+ secure_vector<byte> result;
result += enc_two_digit(year);
result += enc_two_digit(month);
result += enc_two_digit(day);
return result;
}
-ASN1_Ced::ASN1_Ced(std::string const& str) :
- EAC_Time(str, ASN1_Tag(37))
- {}
-
-ASN1_Ced::ASN1_Ced(u64bit val) :
- EAC_Time(val, ASN1_Tag(37))
- {}
-
-ASN1_Ced::ASN1_Ced(EAC_Time const& other) :
- EAC_Time(other.get_year(),
- other.get_month(),
- other.get_day(),
- ASN1_Tag(37))
- {}
-
-ASN1_Cex::ASN1_Cex(std::string const& str) :
- EAC_Time(str, ASN1_Tag(36))
- {}
-
-ASN1_Cex::ASN1_Cex(u64bit val) :
- EAC_Time(val, ASN1_Tag(36))
- {}
-
-ASN1_Cex::ASN1_Cex(EAC_Time const& other) :
- EAC_Time(other.get_year(),
- other.get_month(),
- other.get_day(),
- ASN1_Tag(36))
- {}
-
}
diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp
index 38f51e8dc..f224d15b9 100644
--- a/src/cert/cvc/cvc_ado.cpp
+++ b/src/cert/cvc/cvc_ado.cpp
@@ -26,7 +26,7 @@ EAC1_1_ADO::EAC1_1_ADO(const std::string& in)
void EAC1_1_ADO::force_decode()
{
- SecureVector<byte> inner_cert;
+ secure_vector<byte> inner_cert;
BER_Decoder(tbs_bits)
.start_cons(ASN1_Tag(33))
.raw_bytes(inner_cert)
@@ -34,7 +34,7 @@ void EAC1_1_ADO::force_decode()
.decode(m_car)
.verify_end();
- SecureVector<byte> req_bits = DER_Encoder()
+ secure_vector<byte> req_bits = DER_Encoder()
.start_cons(ASN1_Tag(33), APPLICATION)
.raw_bytes(inner_cert)
.end_cons()
@@ -45,11 +45,11 @@ void EAC1_1_ADO::force_decode()
sig_algo = m_req.sig_algo;
}
-MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer,
- const MemoryRegion<byte>& tbs_bits,
+std::vector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer,
+ const secure_vector<byte>& tbs_bits,
RandomNumberGenerator& rng)
{
- SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng);
+ secure_vector<byte> concat_sig = signer.sign_message(tbs_bits, rng);
return DER_Encoder()
.start_cons(ASN1_Tag(7), APPLICATION)
@@ -65,11 +65,11 @@ ASN1_Car EAC1_1_ADO::get_car() const
}
void EAC1_1_ADO::decode_info(DataSource& source,
- SecureVector<byte> & res_tbs_bits,
+ secure_vector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig)
{
- SecureVector<byte> concat_sig;
- SecureVector<byte> cert_inner_bits;
+ secure_vector<byte> concat_sig;
+ secure_vector<byte> cert_inner_bits;
ASN1_Car car;
BER_Decoder(source)
@@ -81,7 +81,7 @@ void EAC1_1_ADO::decode_info(DataSource& source,
.decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
.end_cons();
- SecureVector<byte> enc_cert = DER_Encoder()
+ secure_vector<byte> enc_cert = DER_Encoder()
.start_cons(ASN1_Tag(33), APPLICATION)
.raw_bytes(cert_inner_bits)
.end_cons()
@@ -97,7 +97,7 @@ void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const
if(encoding == PEM)
throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object");
- SecureVector<byte> concat_sig(
+ secure_vector<byte> concat_sig(
EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation());
out.write(DER_Encoder()
@@ -108,7 +108,7 @@ void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const
.get_contents());
}
-SecureVector<byte> EAC1_1_ADO::tbs_data() const
+secure_vector<byte> EAC1_1_ADO::tbs_data() const
{
return tbs_bits;
}
diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h
index 65a39fd91..81b89ea00 100644
--- a/src/cert/cvc/cvc_ado.h
+++ b/src/cert/cvc/cvc_ado.h
@@ -43,9 +43,9 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
* @param tbs_bits the TBS data to sign
* @param rng a random number generator
*/
- static MemoryVector<byte> make_signed(
+ static std::vector<byte> make_signed(
PK_Signer& signer,
- const MemoryRegion<byte>& tbs_bits,
+ const secure_vector<byte>& tbs_bits,
RandomNumberGenerator& rng);
/**
@@ -73,7 +73,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
* Get the TBS data of this CVC ADO request.
* @result the TBS data
*/
- SecureVector<byte> tbs_data() const;
+ secure_vector<byte> tbs_data() const;
virtual ~EAC1_1_ADO() {}
private:
@@ -82,7 +82,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
void force_decode();
static void decode_info(DataSource& source,
- SecureVector<byte> & res_tbs_bits,
+ secure_vector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig);
};
diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp
index 54f72ecfc..12558bb80 100644
--- a/src/cert/cvc/cvc_cert.cpp
+++ b/src/cert/cvc/cvc_cert.cpp
@@ -33,8 +33,8 @@ u32bit EAC1_1_CVC::get_chat_value() const
*/
void EAC1_1_CVC::force_decode()
{
- SecureVector<byte> enc_pk;
- SecureVector<byte> enc_chat_val;
+ secure_vector<byte> enc_pk;
+ secure_vector<byte> enc_chat_val;
size_t cpi;
BER_Decoder tbs_cert(tbs_bits);
tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION)
@@ -88,7 +88,7 @@ bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const
&& get_concat_sig() == rhs.get_concat_sig());
}
-ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>&,
+ECDSA_PublicKey* decode_eac1_1_key(const secure_vector<byte>&,
AlgorithmIdentifier&)
{
throw Internal_Error("decode_eac1_1_key: Unimplemented");
@@ -96,7 +96,7 @@ ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>&,
}
EAC1_1_CVC make_cvc_cert(PK_Signer& signer,
- MemoryRegion<byte> const& public_key,
+ secure_vector<byte> const& public_key,
ASN1_Car const& car,
ASN1_Chr const& chr,
byte holder_auth_templ,
@@ -105,12 +105,12 @@ EAC1_1_CVC make_cvc_cert(PK_Signer& signer,
RandomNumberGenerator& rng)
{
OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate"));
- MemoryVector<byte> enc_chat_val;
+ std::vector<byte> enc_chat_val;
enc_chat_val.push_back(holder_auth_templ);
- MemoryVector<byte> enc_cpi;
+ std::vector<byte> enc_cpi;
enc_cpi.push_back(0x00);
- MemoryVector<byte> tbs = DER_Encoder()
+ std::vector<byte> tbs = DER_Encoder()
.encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi
.encode(car)
.raw_bytes(public_key)
@@ -123,7 +123,7 @@ EAC1_1_CVC make_cvc_cert(PK_Signer& signer,
.encode(cex)
.get_contents();
- MemoryVector<byte> signed_cert =
+ std::vector<byte> signed_cert =
EAC1_1_CVC::make_signed(signer,
EAC1_1_CVC::build_cert_body(tbs),
rng);
diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h
index 69d0d824a..20370e64b 100644
--- a/src/cert/cvc/cvc_cert.h
+++ b/src/cert/cvc/cvc_cert.h
@@ -96,7 +96,7 @@ inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs)
* @param rng a random number generator
*/
EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer,
- const MemoryRegion<byte>& public_key,
+ const secure_vector<byte>& public_key,
ASN1_Car const& car,
ASN1_Chr const& chr,
byte holder_auth_templ,
@@ -107,7 +107,7 @@ EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer,
/**
* Decode an EAC encoding ECDSA key
*/
-BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>& enc_key,
+BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const secure_vector<byte>& enc_key,
AlgorithmIdentifier& sig_algo);
}
diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h
index ad61b85bf..a272e316f 100644
--- a/src/cert/cvc/cvc_gen_cert.h
+++ b/src/cert/cvc/cvc_gen_cert.h
@@ -56,14 +56,14 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1
* Get the to-be-signed (TBS) data of this object.
* @result the TBS data of this object
*/
- SecureVector<byte> tbs_data() const;
+ secure_vector<byte> tbs_data() const;
/**
* Build the DER encoded certifcate body of an object
* @param tbs the data to be signed
* @result the correctly encoded body of the object
*/
- static SecureVector<byte> build_cert_body(MemoryRegion<byte> const& tbs);
+ static secure_vector<byte> build_cert_body(secure_vector<byte> const& tbs);
/**
* Create a signed generalized CVC object.
@@ -72,9 +72,9 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1
* @param rng a random number generator
* @result the DER encoded signed generalized CVC object
*/
- static MemoryVector<byte> make_signed(
+ static std::vector<byte> make_signed(
PK_Signer& signer,
- const MemoryRegion<byte>& tbs_bits,
+ const secure_vector<byte>& tbs_bits,
RandomNumberGenerator& rng);
EAC1_1_gen_CVC() { m_pk = 0; }
@@ -88,7 +88,7 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1
bool self_signed;
static void decode_info(DataSource& source,
- SecureVector<byte> & res_tbs_bits,
+ secure_vector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig);
};
@@ -104,12 +104,12 @@ template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const
}
template<typename Derived>
-MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed(
+std::vector<byte> EAC1_1_gen_CVC<Derived>::make_signed(
PK_Signer& signer,
- const MemoryRegion<byte>& tbs_bits,
+ const secure_vector<byte>& tbs_bits,
RandomNumberGenerator& rng) // static
{
- SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng);
+ secure_vector<byte> concat_sig = signer.sign_message(tbs_bits, rng);
return DER_Encoder()
.start_cons(ASN1_Tag(33), APPLICATION)
@@ -125,7 +125,7 @@ Public_Key* EAC1_1_gen_CVC<Derived>::subject_public_key() const
return new ECDSA_PublicKey(*m_pk);
}
-template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs)
+template<typename Derived> secure_vector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(secure_vector<byte> const& tbs)
{
return DER_Encoder()
.start_cons(ASN1_Tag(78), APPLICATION)
@@ -133,15 +133,15 @@ template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cer
.end_cons().get_contents();
}
-template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const
+template<typename Derived> secure_vector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const
{
return build_cert_body(EAC1_1_obj<Derived>::tbs_bits);
}
template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const
{
- SecureVector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation());
- SecureVector<byte> der = DER_Encoder()
+ secure_vector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation());
+ secure_vector<byte> der = DER_Encoder()
.start_cons(ASN1_Tag(33), APPLICATION)
.start_cons(ASN1_Tag(78), APPLICATION)
.raw_bytes(EAC1_1_obj<Derived>::tbs_bits)
@@ -159,10 +159,10 @@ template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_
template<typename Derived>
void EAC1_1_gen_CVC<Derived>::decode_info(
DataSource& source,
- SecureVector<byte> & res_tbs_bits,
+ secure_vector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig)
{
- SecureVector<byte> concat_sig;
+ secure_vector<byte> concat_sig;
BER_Decoder(source)
.start_cons(ASN1_Tag(33))
.start_cons(ASN1_Tag(78))
diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp
index ad9e2f4ca..bd7dee3fa 100644
--- a/src/cert/cvc/cvc_req.cpp
+++ b/src/cert/cvc/cvc_req.cpp
@@ -19,7 +19,7 @@ bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const
void EAC1_1_Req::force_decode()
{
- SecureVector<byte> enc_pk;
+ secure_vector<byte> enc_pk;
BER_Decoder tbs_cert(tbs_bits);
size_t cpi;
tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION)
diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h
index 1e8cea7f8..ac4e22453 100644
--- a/src/cert/cvc/cvc_req.h
+++ b/src/cert/cvc/cvc_req.h
@@ -35,7 +35,7 @@ class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req>
EAC1_1_Req(DataSource& source);
/**
- * Construct a CVC request from a DER encoded CVC reqeust file.
+ * Construct a CVC request from a DER encoded CVC request file.
* @param str the path to the DER encoded file
*/
EAC1_1_Req(const std::string& str);
diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp
index 662a1d2be..e692bc9b8 100644
--- a/src/cert/cvc/cvc_self.cpp
+++ b/src/cert/cvc/cvc_self.cpp
@@ -8,7 +8,6 @@
#include <botan/cvc_self.h>
#include <botan/ecc_key.h>
#include <botan/point_gfp.h>
-#include <botan/time.h>
#include <botan/oids.h>
#include <sstream>
#include <memory>
@@ -35,7 +34,7 @@ void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag)
der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag);
}
-MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key,
+std::vector<byte> eac_1_1_encoding(const EC_PublicKey* key,
const OID& sig_algo)
{
if(key->domain_format() == EC_DOMPAR_ENC_OID)
@@ -107,7 +106,7 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
PK_Signer signer(*priv_key, padding_and_hash);
- MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
+ std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
return make_cvc_cert(signer,
enc_public_key,
@@ -134,17 +133,17 @@ EAC1_1_Req create_cvc_req(Private_Key const& key,
PK_Signer signer(*priv_key, padding_and_hash);
- MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
+ std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
- MemoryVector<byte> enc_cpi;
+ std::vector<byte> enc_cpi;
enc_cpi.push_back(0x00);
- MemoryVector<byte> tbs = DER_Encoder()
+ std::vector<byte> tbs = DER_Encoder()
.encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION)
.raw_bytes(enc_public_key)
.encode(chr)
.get_contents();
- MemoryVector<byte> signed_cert =
+ std::vector<byte> signed_cert =
EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer,
EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs),
rng);
@@ -164,12 +163,13 @@ EAC1_1_ADO create_ado_req(Private_Key const& key,
{
throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
}
+
std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid);
PK_Signer signer(*priv_key, padding_and_hash);
- SecureVector<byte> tbs_bits = req.BER_encode();
+ secure_vector<byte> tbs_bits = req.BER_encode();
tbs_bits += DER_Encoder().encode(car).get_contents();
- MemoryVector<byte> signed_cert =
+ std::vector<byte> signed_cert =
EAC1_1_ADO::make_signed(signer, tbs_bits, rng);
DataSource_Memory source(signed_cert);
@@ -193,9 +193,8 @@ EAC1_1_CVC create_cvca(Private_Key const& key,
}
EAC1_1_CVC_Options opts;
opts.car = car;
- const u64bit current_time = system_time();
- opts.ced = ASN1_Ced(current_time);
+ opts.ced = ASN1_Ced(std::chrono::system_clock::now());
opts.cex = ASN1_Cex(opts.ced);
opts.cex.add_months(cvca_validity_months);
opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT));
@@ -210,12 +209,12 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
EAC1_1_CVC const& signee,
RandomNumberGenerator& rng)
{
- ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ const ECDSA_PrivateKey* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+
if (priv_key == 0)
- {
- throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
- }
- ASN1_Ced ced(system_time());
+ throw Invalid_Argument("link_cvca(): unsupported key type");
+
+ ASN1_Ced ced(std::chrono::system_clock::now());
ASN1_Cex cex(signee.get_cex());
if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex))
{
@@ -232,11 +231,11 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
AlgorithmIdentifier sig_algo = signer.signature_algorithm();
std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid);
PK_Signer pk_signer(*priv_key, padding_and_hash);
- std::auto_ptr<Public_Key> pk(signee.subject_public_key());
+ std::unique_ptr<Public_Key> pk(signee.subject_public_key());
ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT);
- MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
+ std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
return make_cvc_cert(pk_signer, enc_public_key,
signer.get_car(),
@@ -262,13 +261,19 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
}
std::string chr_str = signee.get_chr().value();
- chr_str += to_string(seqnr, seqnr_len);
+
+ std::string seqnr_string = std::to_string(seqnr);
+
+ while(seqnr_string.size() < seqnr_len)
+ seqnr_string = '0' + seqnr_string;
+
+ chr_str += seqnr_string;
ASN1_Chr chr(chr_str);
std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid);
PK_Signer pk_signer(*priv_key, padding_and_hash);
- std::auto_ptr<Public_Key> pk(signee.subject_public_key());
+ std::unique_ptr<Public_Key> pk(signee.subject_public_key());
ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
- std::auto_ptr<Public_Key> signer_pk(signer_cert.subject_public_key());
+ std::unique_ptr<Public_Key> signer_pk(signer_cert.subject_public_key());
// for the case that the domain parameters are not set...
// (we use those from the signer because they must fit)
@@ -277,8 +282,9 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm());
- const u64bit current_time = system_time();
- ASN1_Ced ced(current_time);
+
+ ASN1_Ced ced(std::chrono::system_clock::now());
+
u32bit chat_val;
u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer
ASN1_Cex cex(ced);
@@ -303,7 +309,7 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
// (IS cannot sign certificates)
}
- MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
+ std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
return make_cvc_cert(pk_signer, enc_public_key,
ASN1_Car(signer_cert.get_chr().iso_8859()),
diff --git a/src/cert/cvc/eac_asn_obj.h b/src/cert/cvc/eac_asn_obj.h
index d0bab6fdd..9937abb01 100644
--- a/src/cert/cvc/eac_asn_obj.h
+++ b/src/cert/cvc/eac_asn_obj.h
@@ -56,7 +56,6 @@ class BOTAN_DLL EAC_Time : public ASN1_Object
* e.g. "2007 08 01"
*/
void set_to(const std::string& str);
- //void set_to(const std::string&, ASN1_Tag);
/**
* Add the specified number of years to this.
@@ -74,28 +73,32 @@ class BOTAN_DLL EAC_Time : public ASN1_Object
* Get the year value of this objects.
* @return year value
*/
- u32bit get_year() const;
+ u32bit get_year() const { return year; }
/**
* Get the month value of this objects.
* @return month value
*/
- u32bit get_month() const;
+ u32bit get_month() const { return month; }
/**
* Get the day value of this objects.
* @return day value
*/
- u32bit get_day() const;
+ u32bit get_day() const { return day; }
- EAC_Time(u64bit, ASN1_Tag t = ASN1_Tag(0));
- //EAC_Time(const std::string& = "");
- EAC_Time(const std::string&, ASN1_Tag = ASN1_Tag(0));
- EAC_Time(u32bit year, u32bit month, u32bit day, ASN1_Tag = ASN1_Tag(0));
+ EAC_Time(const std::chrono::system_clock::time_point& time,
+ ASN1_Tag tag = ASN1_Tag(0));
+
+ EAC_Time(const std::string& yyyy_mm_dd,
+ ASN1_Tag tag = ASN1_Tag(0));
+
+ EAC_Time(u32bit year, u32bit month, u32bit day,
+ ASN1_Tag tag = ASN1_Tag(0));
virtual ~EAC_Time() {}
private:
- SecureVector<byte> encoded_eac_time() const;
+ secure_vector<byte> encoded_eac_time() const;
bool passes_sanity_check() const;
u32bit year, month, day;
ASN1_Tag tag;
@@ -113,25 +116,25 @@ class BOTAN_DLL ASN1_Ced : public EAC_Time
* @param str a string in the format "yyyy mm dd",
* e.g. "2007 08 01"
*/
- ASN1_Ced(std::string const& str = "");
+ ASN1_Ced(const std::string& str = "") :
+ EAC_Time(str, ASN1_Tag(37)) {}
/**
- * Construct a CED from a timer value.
- * @param time the number of seconds elapsed midnight, 1st
- * January 1970 GMT (or 7pm, 31st December 1969 EST) up to the
- * desired date
+ * Construct a CED from a time point
*/
- ASN1_Ced(u64bit time);
+ ASN1_Ced(const std::chrono::system_clock::time_point& time) :
+ EAC_Time(time, ASN1_Tag(37)) {}
/**
* Copy constructor (for general EAC_Time objects).
* @param other the object to copy from
*/
- ASN1_Ced(EAC_Time const& other);
- //ASN1_Ced(ASN1_Cex const& cex);
+ ASN1_Ced(const EAC_Time& other) :
+ EAC_Time(other.get_year(), other.get_month(), other.get_day(),
+ ASN1_Tag(37))
+ {}
};
-
/**
* This class represents CVC CEXs. Only limited sanity checks of
* the inputted date value are performed.
@@ -140,27 +143,20 @@ class BOTAN_DLL ASN1_Cex : public EAC_Time
{
public:
/**
- * Construct a CED from a string value.
+ * Construct a CEX from a string value.
* @param str a string in the format "yyyy mm dd",
* e.g. "2007 08 01"
*/
- ASN1_Cex(std::string const& str="");
+ ASN1_Cex(const std::string& str = "") :
+ EAC_Time(str, ASN1_Tag(36)) {}
- /**
- * Construct a CED from a timer value.
- * @param time the number of seconds elapsed
- * midnight, 1st
- * January 1970 GMT (or 7pm, 31st December 1969 EST)
- * up to the desired date
- */
- ASN1_Cex(u64bit time);
+ ASN1_Cex(const std::chrono::system_clock::time_point& time) :
+ EAC_Time(time, ASN1_Tag(36)) {}
- /**
- * Copy constructor (for general EAC_Time objects).
- * @param other the object to copy from
- */
- ASN1_Cex(EAC_Time const& other);
- //ASN1_Cex(ASN1_Ced const& ced);
+ ASN1_Cex(const EAC_Time& other) :
+ EAC_Time(other.get_year(), other.get_month(), other.get_day(),
+ ASN1_Tag(36))
+ {}
};
/**
diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h
index eb6db3369..39f34b874 100644
--- a/src/cert/cvc/eac_obj.h
+++ b/src/cert/cvc/eac_obj.h
@@ -24,7 +24,7 @@ class EAC1_1_obj : public EAC_Signed_Object
* Return the signature as a concatenation of the encoded parts.
* @result the concatenated signature
*/
- SecureVector<byte> get_concat_sig() const
+ secure_vector<byte> get_concat_sig() const
{ return m_sig.get_concatenation(); }
bool check_signature(class Public_Key& key) const
diff --git a/src/cert/cvc/ecdsa_sig.cpp b/src/cert/cvc/ecdsa_sig.cpp
index e8fd7f051..91166ad79 100644
--- a/src/cert/cvc/ecdsa_sig.cpp
+++ b/src/cert/cvc/ecdsa_sig.cpp
@@ -10,7 +10,7 @@
namespace Botan {
-ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber)
+ECDSA_Signature::ECDSA_Signature(const secure_vector<byte>& ber)
{
BER_Decoder(ber)
.start_cons(SEQUENCE)
@@ -20,7 +20,7 @@ ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber)
.verify_end();
}
-MemoryVector<byte> ECDSA_Signature::DER_encode() const
+std::vector<byte> ECDSA_Signature::DER_encode() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -30,20 +30,20 @@ MemoryVector<byte> ECDSA_Signature::DER_encode() const
.get_contents();
}
-MemoryVector<byte> ECDSA_Signature::get_concatenation() const
+std::vector<byte> ECDSA_Signature::get_concatenation() const
{
// use the larger
const size_t enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes();
- SecureVector<byte> sv_r = BigInt::encode_1363(m_r, enc_len);
- SecureVector<byte> sv_s = BigInt::encode_1363(m_s, enc_len);
+ secure_vector<byte> sv_r = BigInt::encode_1363(m_r, enc_len);
+ secure_vector<byte> sv_s = BigInt::encode_1363(m_s, enc_len);
- SecureVector<byte> result(sv_r);
+ secure_vector<byte> result(sv_r);
result += sv_s;
return result;
}
-ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concat)
+ECDSA_Signature decode_concatenation(const secure_vector<byte>& concat)
{
if(concat.size() % 2 != 0)
throw Invalid_Argument("Erroneous length of signature");
diff --git a/src/cert/cvc/ecdsa_sig.h b/src/cert/cvc/ecdsa_sig.h
index a92052470..a92d5078c 100644
--- a/src/cert/cvc/ecdsa_sig.h
+++ b/src/cert/cvc/ecdsa_sig.h
@@ -27,7 +27,7 @@ class BOTAN_DLL ECDSA_Signature
ECDSA_Signature(const BigInt& r, const BigInt& s) :
m_r(r), m_s(s) {}
- ECDSA_Signature(const MemoryRegion<byte>& ber);
+ ECDSA_Signature(const secure_vector<byte>& ber);
const BigInt& get_r() const { return m_r; }
const BigInt& get_s() const { return m_s; }
@@ -35,9 +35,9 @@ class BOTAN_DLL ECDSA_Signature
/**
* return the r||s
*/
- MemoryVector<byte> get_concatenation() const;
+ std::vector<byte> get_concatenation() const;
- MemoryVector<byte> DER_encode() const;
+ std::vector<byte> DER_encode() const;
bool operator==(const ECDSA_Signature& other) const
{
@@ -54,7 +54,7 @@ inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs)
return !(lhs == rhs);
}
-ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concatenation);
+ECDSA_Signature decode_concatenation(const secure_vector<byte>& concatenation);
}
diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt
index 33a872053..3cf759188 100644
--- a/src/cert/cvc/info.txt
+++ b/src/cert/cvc/info.txt
@@ -1,5 +1,4 @@
define CARD_VERIFIABLE_CERTIFICATES
-
load_on request
<header:public>
diff --git a/src/cert/cvc/signed_obj.cpp b/src/cert/cvc/signed_obj.cpp
index d6aa2f02b..4f04cd72e 100644
--- a/src/cert/cvc/signed_obj.cpp
+++ b/src/cert/cvc/signed_obj.cpp
@@ -16,7 +16,7 @@ namespace Botan {
/*
* Return a BER encoded X.509 object
*/
-SecureVector<byte> EAC_Signed_Object::BER_encode() const
+secure_vector<byte> EAC_Signed_Object::BER_encode() const
{
Pipe ber;
ber.start_msg();
@@ -46,7 +46,7 @@ AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const
}
bool EAC_Signed_Object::check_signature(Public_Key& pub_key,
- const MemoryRegion<byte>& sig) const
+ const secure_vector<byte>& sig) const
{
try
{
@@ -62,7 +62,7 @@ bool EAC_Signed_Object::check_signature(Public_Key& pub_key,
Signature_Format format =
(pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
- SecureVector<byte> to_sign = tbs_data();
+ secure_vector<byte> to_sign = tbs_data();
PK_Verifier verifier(pub_key, padding, format);
return verifier.verify_message(to_sign, sig);
diff --git a/src/cert/cvc/signed_obj.h b/src/cert/cvc/signed_obj.h
index 20f0e7b14..45bd2858e 100644
--- a/src/cert/cvc/signed_obj.h
+++ b/src/cert/cvc/signed_obj.h
@@ -26,7 +26,7 @@ class BOTAN_DLL EAC_Signed_Object
* Get the TBS (to-be-signed) data in this object.
* @return DER encoded TBS data of this object
*/
- virtual SecureVector<byte> tbs_data() const = 0;
+ virtual secure_vector<byte> tbs_data() const = 0;
/**
* Get the signature of this object as a concatenation, i.e. if the
@@ -39,7 +39,7 @@ class BOTAN_DLL EAC_Signed_Object
NOTE: this is here only because abstract signature objects have
not yet been introduced
*/
- virtual SecureVector<byte> get_concat_sig() const = 0;
+ virtual secure_vector<byte> get_concat_sig() const = 0;
/**
* Get the signature algorithm identifier used to sign this object.
@@ -55,7 +55,7 @@ class BOTAN_DLL EAC_Signed_Object
* associated with this public key
*/
bool check_signature(class Public_Key& key,
- const MemoryRegion<byte>& sig) const;
+ const secure_vector<byte>& sig) const;
/**
* Write this object DER encoded into a specified pipe.
@@ -69,7 +69,7 @@ class BOTAN_DLL EAC_Signed_Object
* BER encode this object.
* @return result containing the BER representation of this object.
*/
- SecureVector<byte> BER_encode() const;
+ secure_vector<byte> BER_encode() const;
/**
* PEM encode this object.
@@ -83,7 +83,7 @@ class BOTAN_DLL EAC_Signed_Object
EAC_Signed_Object() {}
AlgorithmIdentifier sig_algo;
- SecureVector<byte> tbs_bits;
+ secure_vector<byte> tbs_bits;
std::string PEM_label_pref;
std::vector<std::string> PEM_labels_allowed;
private:
diff --git a/src/cert/x509/certstor.cpp b/src/cert/x509/certstor.cpp
index de27361ed..293072785 100644
--- a/src/cert/x509/certstor.cpp
+++ b/src/cert/x509/certstor.cpp
@@ -32,7 +32,7 @@ void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert)
std::vector<X509_Certificate>
Certificate_Store_In_Memory::find_cert_by_subject_and_key_id(
const X509_DN& subject_dn,
- const MemoryRegion<byte>& key_id) const
+ const std::vector<byte>& key_id) const
{
std::vector<X509_Certificate> result;
@@ -41,7 +41,7 @@ Certificate_Store_In_Memory::find_cert_by_subject_and_key_id(
// Only compare key ids if set in both call and in the cert
if(key_id.size())
{
- MemoryVector<byte> skid = certs[i].subject_key_id();
+ std::vector<byte> skid = certs[i].subject_key_id();
if(skid.size() && skid != key_id) // no match
continue;
@@ -76,7 +76,7 @@ void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl)
std::vector<X509_CRL>
Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id(
const X509_DN& issuer_dn,
- const MemoryRegion<byte>& key_id) const
+ const std::vector<byte>& key_id) const
{
std::vector<X509_CRL> result;
@@ -85,7 +85,7 @@ Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id(
// Only compare key ids if set in both call and in the CRL
if(key_id.size())
{
- MemoryVector<byte> akid = crls[i].authority_key_id();
+ std::vector<byte> akid = crls[i].authority_key_id();
if(akid.size() && akid != key_id) // no match
continue;
diff --git a/src/cert/x509/certstor.h b/src/cert/x509/certstor.h
index e2727c569..584259f8c 100644
--- a/src/cert/x509/certstor.h
+++ b/src/cert/x509/certstor.h
@@ -39,7 +39,7 @@ class BOTAN_DLL Certificate_Store
virtual std::vector<X509_Certificate>
find_cert_by_subject_and_key_id(
const X509_DN& subject_dn,
- const MemoryRegion<byte>& key_id) const = 0;
+ const std::vector<byte>& key_id) const = 0;
/**
* Find CRLs by the DN and key id of the issuer
@@ -47,7 +47,7 @@ class BOTAN_DLL Certificate_Store
virtual std::vector<X509_CRL>
find_crl_by_issuer_and_key_id(
const X509_DN& issuer_dn,
- const MemoryRegion<byte>& key_id) const = 0;
+ const std::vector<byte>& key_id) const = 0;
};
/**
@@ -62,11 +62,11 @@ class BOTAN_DLL Certificate_Store_In_Memory : public Certificate_Store
std::vector<X509_Certificate> find_cert_by_subject_and_key_id(
const X509_DN& subject_dn,
- const MemoryRegion<byte>& key_id) const;
+ const std::vector<byte>& key_id) const;
std::vector<X509_CRL> find_crl_by_issuer_and_key_id(
const X509_DN& issuer_dn,
- const MemoryRegion<byte>& key_id) const;
+ const std::vector<byte>& key_id) const;
Certificate_Store_In_Memory() {}
private:
diff --git a/src/cert/x509/crl_ent.cpp b/src/cert/x509/crl_ent.cpp
index d566637f6..a5663e6bb 100644
--- a/src/cert/x509/crl_ent.cpp
+++ b/src/cert/x509/crl_ent.cpp
@@ -11,7 +11,6 @@
#include <botan/ber_dec.h>
#include <botan/bigint.h>
#include <botan/oids.h>
-#include <botan/time.h>
namespace Botan {
@@ -31,7 +30,7 @@ CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) :
throw_on_unknown_critical(false)
{
serial = cert.serial_number();
- time = X509_Time(system_time());
+ time = X509_Time(std::chrono::system_clock::now());
reason = why;
}
diff --git a/src/cert/x509/crl_ent.h b/src/cert/x509/crl_ent.h
index ae9535484..769519f78 100644
--- a/src/cert/x509/crl_ent.h
+++ b/src/cert/x509/crl_ent.h
@@ -45,7 +45,7 @@ class BOTAN_DLL CRL_Entry : public ASN1_Object
* Get the serial number of the certificate associated with this entry.
* @return certificate's serial number
*/
- MemoryVector<byte> serial_number() const { return serial; }
+ std::vector<byte> serial_number() const { return serial; }
/**
* Get the revocation date of the certificate associated with this entry
@@ -74,7 +74,7 @@ class BOTAN_DLL CRL_Entry : public ASN1_Object
private:
bool throw_on_unknown_critical;
- MemoryVector<byte> serial;
+ std::vector<byte> serial;
X509_Time time;
CRL_Code reason;
};
diff --git a/src/cert/x509/pkcs10.cpp b/src/cert/x509/pkcs10.cpp
index 784318d3d..c67f74142 100644
--- a/src/cert/x509/pkcs10.cpp
+++ b/src/cert/x509/pkcs10.cpp
@@ -35,6 +35,15 @@ PKCS10_Request::PKCS10_Request(const std::string& in) :
}
/*
+* PKCS10_Request Constructor
+*/
+PKCS10_Request::PKCS10_Request(const std::vector<byte>& in) :
+ X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST")
+ {
+ do_decode();
+ }
+
+/*
* Deocde the CertificateRequestInfo
*/
void PKCS10_Request::force_decode()
@@ -45,7 +54,7 @@ void PKCS10_Request::force_decode()
cert_req_info.decode(version);
if(version != 0)
throw Decoding_Error("Unknown version code in PKCS #10 request: " +
- to_string(version));
+ std::to_string(version));
X509_DN dn_subject;
cert_req_info.decode(dn_subject);
@@ -59,7 +68,7 @@ void PKCS10_Request::force_decode()
info.add("X509.Certificate.public_key",
PEM_Code::encode(
- ASN1::put_in_sequence(public_key.value),
+ ASN1::put_in_sequence(unlock(public_key.value)),
"PUBLIC KEY"
)
);
@@ -136,10 +145,10 @@ X509_DN PKCS10_Request::subject_dn() const
/*
* Return the public key of the requestor
*/
-MemoryVector<byte> PKCS10_Request::raw_public_key() const
+std::vector<byte> PKCS10_Request::raw_public_key() const
{
DataSource_Memory source(info.get1("X509.Certificate.public_key"));
- return PEM_Code::decode_check_label(source, "PUBLIC KEY");
+ return unlock(PEM_Code::decode_check_label(source, "PUBLIC KEY"));
}
/*
diff --git a/src/cert/x509/pkcs10.h b/src/cert/x509/pkcs10.h
index 065dfbdc0..974ea0070 100644
--- a/src/cert/x509/pkcs10.h
+++ b/src/cert/x509/pkcs10.h
@@ -33,7 +33,7 @@ class BOTAN_DLL PKCS10_Request : public X509_Object
* Get the raw DER encoded public key.
* @return raw DER encoded public key
*/
- MemoryVector<byte> raw_public_key() const;
+ std::vector<byte> raw_public_key() const;
/**
* Get the subject DN.
@@ -91,6 +91,12 @@ class BOTAN_DLL PKCS10_Request : public X509_Object
* encoded request file
*/
PKCS10_Request(const std::string& filename);
+
+ /**
+ * Create a PKCS#10 Request from binary data.
+ * @param vec a std::vector containing the DER value
+ */
+ PKCS10_Request(const std::vector<byte>& vec);
private:
void force_decode();
void handle_attribute(const Attribute&);
diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp
index 77e066533..9633d1466 100644
--- a/src/cert/x509/x509_ca.cpp
+++ b/src/cert/x509/x509_ca.cpp
@@ -57,8 +57,8 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
else
{
- std::auto_ptr<Public_Key> key(req.subject_public_key());
- constraints = find_constraints(*key, req.constraints());
+ std::unique_ptr<Public_Key> key(req.subject_public_key());
+ constraints = X509::find_constraints(*key, req.constraints());
}
Extensions extensions;
@@ -91,7 +91,7 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
X509_Certificate X509_CA::make_cert(PK_Signer* signer,
RandomNumberGenerator& rng,
const AlgorithmIdentifier& sig_algo,
- const MemoryRegion<byte>& pub_key,
+ const std::vector<byte>& pub_key,
const X509_Time& not_before,
const X509_Time& not_after,
const X509_DN& issuer_dn,
@@ -103,35 +103,35 @@ X509_Certificate X509_CA::make_cert(PK_Signer* signer,
BigInt serial_no(rng, SERIAL_BITS);
- DataSource_Memory source(X509_Object::make_signed(signer, rng, sig_algo,
- DER_Encoder().start_cons(SEQUENCE)
- .start_explicit(0)
- .encode(X509_CERT_VERSION-1)
- .end_explicit()
+ const std::vector<byte> cert = X509_Object::make_signed(
+ signer, rng, sig_algo,
+ DER_Encoder().start_cons(SEQUENCE)
+ .start_explicit(0)
+ .encode(X509_CERT_VERSION-1)
+ .end_explicit()
- .encode(serial_no)
+ .encode(serial_no)
- .encode(sig_algo)
- .encode(issuer_dn)
+ .encode(sig_algo)
+ .encode(issuer_dn)
- .start_cons(SEQUENCE)
- .encode(not_before)
- .encode(not_after)
- .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(not_before)
+ .encode(not_after)
+ .end_cons()
- .encode(subject_dn)
- .raw_bytes(pub_key)
+ .encode(subject_dn)
+ .raw_bytes(pub_key)
- .start_explicit(3)
- .start_cons(SEQUENCE)
- .encode(extensions)
- .end_cons()
- .end_explicit()
- .end_cons()
- .get_contents()
- ));
+ .start_explicit(3)
+ .start_cons(SEQUENCE)
+ .encode(extensions)
+ .end_cons()
+ .end_explicit()
+ .end_cons()
+ .get_contents());
- return X509_Certificate(source);
+ return X509_Certificate(cert);
}
/*
@@ -173,36 +173,37 @@ X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
next_update = timespec_to_u32bit("7d");
// Totally stupid: ties encoding logic to the return of std::time!!
- const u64bit current_time = system_time();
+ auto current_time = std::chrono::system_clock::now();
+ auto expire_time = current_time + std::chrono::seconds(next_update);
Extensions extensions;
extensions.add(
new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
extensions.add(new Cert_Extension::CRL_Number(crl_number));
- DataSource_Memory source(X509_Object::make_signed(signer, rng, ca_sig_algo,
- DER_Encoder().start_cons(SEQUENCE)
- .encode(X509_CRL_VERSION-1)
- .encode(ca_sig_algo)
- .encode(cert.issuer_dn())
- .encode(X509_Time(current_time))
- .encode(X509_Time(current_time + next_update))
- .encode_if(revoked.size() > 0,
- DER_Encoder()
- .start_cons(SEQUENCE)
- .encode_list(revoked)
- .end_cons()
- )
- .start_explicit(0)
- .start_cons(SEQUENCE)
- .encode(extensions)
- .end_cons()
- .end_explicit()
- .end_cons()
- .get_contents()
- ));
+ const std::vector<byte> crl = X509_Object::make_signed(
+ signer, rng, ca_sig_algo,
+ DER_Encoder().start_cons(SEQUENCE)
+ .encode(X509_CRL_VERSION-1)
+ .encode(ca_sig_algo)
+ .encode(cert.issuer_dn())
+ .encode(X509_Time(current_time))
+ .encode(X509_Time(expire_time))
+ .encode_if(revoked.size() > 0,
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(revoked)
+ .end_cons()
+ )
+ .start_explicit(0)
+ .start_cons(SEQUENCE)
+ .encode(extensions)
+ .end_cons()
+ .end_explicit()
+ .end_cons()
+ .get_contents());
- return X509_CRL(source);
+ return X509_CRL(crl);
}
/*
diff --git a/src/cert/x509/x509_ca.h b/src/cert/x509/x509_ca.h
index 97be6a415..d37b02eaf 100644
--- a/src/cert/x509/x509_ca.h
+++ b/src/cert/x509/x509_ca.h
@@ -82,7 +82,7 @@ class BOTAN_DLL X509_CA
static X509_Certificate make_cert(PK_Signer* signer,
RandomNumberGenerator& rng,
const AlgorithmIdentifier& sig_algo,
- const MemoryRegion<byte>& pub_key,
+ const std::vector<byte>& pub_key,
const X509_Time& not_before,
const X509_Time& not_after,
const X509_DN& issuer_dn,
@@ -99,11 +99,11 @@ class BOTAN_DLL X509_CA
const Private_Key& key,
const std::string& hash_fn);
+ X509_CA(const X509_CA&) = delete;
+ X509_CA& operator=(const X509_CA&) = delete;
+
~X509_CA();
private:
- X509_CA(const X509_CA&) {}
- X509_CA& operator=(const X509_CA&) { return (*this); }
-
X509_CRL make_crl(const std::vector<CRL_Entry>& entries,
u32bit crl_number, u32bit next_update,
RandomNumberGenerator& rng) const;
diff --git a/src/cert/x509/x509_crl.cpp b/src/cert/x509/x509_crl.cpp
index 9c6b891c7..1d6393470 100644
--- a/src/cert/x509/x509_crl.cpp
+++ b/src/cert/x509/x509_crl.cpp
@@ -33,6 +33,12 @@ X509_CRL::X509_CRL(const std::string& in, bool touc) :
do_decode();
}
+X509_CRL::X509_CRL(const std::vector<byte>& in, bool touc) :
+ X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(touc)
+ {
+ do_decode();
+ }
+
/**
* Check if this particular certificate is listed in the CRL
*/
@@ -82,7 +88,7 @@ void X509_CRL::force_decode()
if(version != 0 && version != 1)
throw X509_CRL_Error("Unknown X.509 CRL version " +
- to_string(version+1));
+ std::to_string(version+1));
AlgorithmIdentifier sig_algo_inner;
tbs_crl.decode(sig_algo_inner);
@@ -153,7 +159,7 @@ X509_DN X509_CRL::issuer_dn() const
/*
* Return the key identifier of the issuer
*/
-MemoryVector<byte> X509_CRL::authority_key_id() const
+std::vector<byte> X509_CRL::authority_key_id() const
{
return info.get1_memvec("X509v3.AuthorityKeyIdentifier");
}
diff --git a/src/cert/x509/x509_crl.h b/src/cert/x509/x509_crl.h
index 55eb8424b..3e45df121 100644
--- a/src/cert/x509/x509_crl.h
+++ b/src/cert/x509/x509_crl.h
@@ -52,7 +52,7 @@ class BOTAN_DLL X509_CRL : public X509_Object
* Get the AuthorityKeyIdentifier of this CRL.
* @return this CRLs AuthorityKeyIdentifier
*/
- MemoryVector<byte> authority_key_id() const;
+ std::vector<byte> authority_key_id() const;
/**
* Get the serial number of this CRL.
@@ -88,6 +88,16 @@ class BOTAN_DLL X509_CRL : public X509_Object
*/
X509_CRL(const std::string& filename,
bool throw_on_unknown_critical = false);
+
+ /**
+ * Construct a CRL from a binary vector
+ * @param vec the binary (DER) representation of the CRL
+ * @param throw_on_unknown_critical should we throw an exception
+ * if an unknown CRL extension marked as critical is encountered.
+ */
+ X509_CRL(const std::vector<byte>& vec,
+ bool throw_on_unknown_critical = false);
+
private:
void force_decode();
diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp
index 6e0befaf3..919fb790a 100644
--- a/src/cert/x509/x509_ext.cpp
+++ b/src/cert/x509/x509_ext.cpp
@@ -36,7 +36,7 @@ Certificate_Extension* Extensions::get_extension(const OID& oid)
X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies);
X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode);
- return 0;
+ return nullptr;
}
/*
@@ -114,7 +114,7 @@ void Extensions::decode_from(BER_Decoder& from_source)
while(sequence.more_items())
{
OID oid;
- MemoryVector<byte> value;
+ std::vector<byte> value;
bool critical;
sequence.start_cons(SEQUENCE)
@@ -176,7 +176,7 @@ size_t Basic_Constraints::get_path_limit() const
/*
* Encode the extension
*/
-MemoryVector<byte> Basic_Constraints::encode_inner() const
+std::vector<byte> Basic_Constraints::encode_inner() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -186,13 +186,13 @@ MemoryVector<byte> Basic_Constraints::encode_inner() const
.encode_optional(path_limit, NO_CERT_PATH_LIMIT)
)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in)
+void Basic_Constraints::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in)
.start_cons(SEQUENCE)
@@ -217,14 +217,14 @@ void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const
/*
* Encode the extension
*/
-MemoryVector<byte> Key_Usage::encode_inner() const
+std::vector<byte> Key_Usage::encode_inner() const
{
if(constraints == NO_CONSTRAINTS)
throw Encoding_Error("Cannot encode zero usage constraints");
const size_t unused_bits = low_bit(constraints) - 1;
- MemoryVector<byte> der;
+ std::vector<byte> der;
der.push_back(BIT_STRING);
der.push_back(2 + ((unused_bits < 8) ? 1 : 0));
der.push_back(unused_bits % 8);
@@ -238,7 +238,7 @@ MemoryVector<byte> Key_Usage::encode_inner() const
/*
* Decode the extension
*/
-void Key_Usage::decode_inner(const MemoryRegion<byte>& in)
+void Key_Usage::decode_inner(const std::vector<byte>& in)
{
BER_Decoder ber(in);
@@ -274,15 +274,15 @@ void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
/*
* Encode the extension
*/
-MemoryVector<byte> Subject_Key_ID::encode_inner() const
+std::vector<byte> Subject_Key_ID::encode_inner() const
{
- return DER_Encoder().encode(key_id, OCTET_STRING).get_contents();
+ return DER_Encoder().encode(key_id, OCTET_STRING).get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in)
+void Subject_Key_ID::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end();
}
@@ -298,28 +298,28 @@ void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const
/*
* Subject_Key_ID Constructor
*/
-Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key)
+Subject_Key_ID::Subject_Key_ID(const std::vector<byte>& pub_key)
{
SHA_160 hash;
- key_id = hash.process(pub_key);
+ key_id = unlock(hash.process(pub_key));
}
/*
* Encode the extension
*/
-MemoryVector<byte> Authority_Key_ID::encode_inner() const
+std::vector<byte> Authority_Key_ID::encode_inner() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in)
+void Authority_Key_ID::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in)
.start_cons(SEQUENCE)
@@ -338,15 +338,15 @@ void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const
/*
* Encode the extension
*/
-MemoryVector<byte> Alternative_Name::encode_inner() const
+std::vector<byte> Alternative_Name::encode_inner() const
{
- return DER_Encoder().encode(alt_name).get_contents();
+ return DER_Encoder().encode(alt_name).get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Alternative_Name::decode_inner(const MemoryRegion<byte>& in)
+void Alternative_Name::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in).decode(alt_name);
}
@@ -404,19 +404,19 @@ Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
/*
* Encode the extension
*/
-MemoryVector<byte> Extended_Key_Usage::encode_inner() const
+std::vector<byte> Extended_Key_Usage::encode_inner() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
.encode_list(oids)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in)
+void Extended_Key_Usage::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in)
.start_cons(SEQUENCE)
@@ -467,7 +467,7 @@ class Policy_Information : public ASN1_Object
/*
* Encode the extension
*/
-MemoryVector<byte> Certificate_Policies::encode_inner() const
+std::vector<byte> Certificate_Policies::encode_inner() const
{
std::vector<Policy_Information> policies;
@@ -478,13 +478,13 @@ MemoryVector<byte> Certificate_Policies::encode_inner() const
.start_cons(SEQUENCE)
.encode_list(policies)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
* Decode the extension
*/
-void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in)
+void Certificate_Policies::decode_inner(const std::vector<byte>& in)
{
std::vector<Policy_Information> policies;
@@ -530,15 +530,15 @@ CRL_Number* CRL_Number::copy() const
/*
* Encode the extension
*/
-MemoryVector<byte> CRL_Number::encode_inner() const
+std::vector<byte> CRL_Number::encode_inner() const
{
- return DER_Encoder().encode(crl_number).get_contents();
+ return DER_Encoder().encode(crl_number).get_contents_unlocked();
}
/*
* Decode the extension
*/
-void CRL_Number::decode_inner(const MemoryRegion<byte>& in)
+void CRL_Number::decode_inner(const std::vector<byte>& in)
{
BER_Decoder(in).decode(crl_number);
}
@@ -554,17 +554,17 @@ void CRL_Number::contents_to(Data_Store& info, Data_Store&) const
/*
* Encode the extension
*/
-MemoryVector<byte> CRL_ReasonCode::encode_inner() const
+std::vector<byte> CRL_ReasonCode::encode_inner() const
{
return DER_Encoder()
.encode(static_cast<size_t>(reason), ENUMERATED, UNIVERSAL)
- .get_contents();
+ .get_contents_unlocked();
}
/*
* Decode the extension
*/
-void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in)
+void CRL_ReasonCode::decode_inner(const std::vector<byte>& in)
{
size_t reason_code = 0;
BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL);
diff --git a/src/cert/x509/x509_ext.h b/src/cert/x509/x509_ext.h
index 714e29562..1e5d1adbb 100644
--- a/src/cert/x509/x509_ext.h
+++ b/src/cert/x509/x509_ext.h
@@ -56,8 +56,8 @@ class BOTAN_DLL Certificate_Extension
protected:
friend class Extensions;
virtual bool should_encode() const { return true; }
- virtual MemoryVector<byte> encode_inner() const = 0;
- virtual void decode_inner(const MemoryRegion<byte>&) = 0;
+ virtual std::vector<byte> encode_inner() const = 0;
+ virtual void decode_inner(const std::vector<byte>&) = 0;
};
/**
@@ -107,8 +107,8 @@ class BOTAN_DLL Basic_Constraints : public Certificate_Extension
std::string config_id() const { return "basic_constraints"; }
std::string oid_name() const { return "X509v3.BasicConstraints"; }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
bool is_ca;
@@ -131,8 +131,8 @@ class BOTAN_DLL Key_Usage : public Certificate_Extension
std::string oid_name() const { return "X509v3.KeyUsage"; }
bool should_encode() const { return (constraints != NO_CONSTRAINTS); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
Key_Constraints constraints;
@@ -147,19 +147,19 @@ class BOTAN_DLL Subject_Key_ID : public Certificate_Extension
Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); }
Subject_Key_ID() {}
- Subject_Key_ID(const MemoryRegion<byte>&);
+ Subject_Key_ID(const std::vector<byte>&);
- MemoryVector<byte> get_key_id() const { return key_id; }
+ std::vector<byte> get_key_id() const { return key_id; }
private:
std::string config_id() const { return "subject_key_id"; }
std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
- MemoryVector<byte> key_id;
+ std::vector<byte> key_id;
};
/**
@@ -171,19 +171,19 @@ class BOTAN_DLL Authority_Key_ID : public Certificate_Extension
Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); }
Authority_Key_ID() {}
- Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {}
+ Authority_Key_ID(const std::vector<byte>& k) : key_id(k) {}
- MemoryVector<byte> get_key_id() const { return key_id; }
+ std::vector<byte> get_key_id() const { return key_id; }
private:
std::string config_id() const { return "authority_key_id"; }
std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
- MemoryVector<byte> key_id;
+ std::vector<byte> key_id;
};
/**
@@ -204,8 +204,8 @@ class BOTAN_DLL Alternative_Name : public Certificate_Extension
std::string oid_name() const { return oid_name_str; }
bool should_encode() const { return alt_name.has_items(); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::string config_name_str, oid_name_str;
@@ -253,8 +253,8 @@ class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension
std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; }
bool should_encode() const { return (oids.size() > 0); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::vector<OID> oids;
@@ -278,8 +278,8 @@ class BOTAN_DLL Certificate_Policies : public Certificate_Extension
std::string oid_name() const { return "X509v3.CertificatePolicies"; }
bool should_encode() const { return (oids.size() > 0); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::vector<OID> oids;
@@ -302,8 +302,8 @@ class BOTAN_DLL CRL_Number : public Certificate_Extension
std::string oid_name() const { return "X509v3.CRLNumber"; }
bool should_encode() const { return has_value; }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
bool has_value;
@@ -326,8 +326,8 @@ class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
std::string oid_name() const { return "X509v3.ReasonCode"; }
bool should_encode() const { return (reason != UNSPECIFIED); }
- MemoryVector<byte> encode_inner() const;
- void decode_inner(const MemoryRegion<byte>&);
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
CRL_Code reason;
diff --git a/src/cert/x509/x509_obj.cpp b/src/cert/x509/x509_obj.cpp
index 670bd8da6..af8be0384 100644
--- a/src/cert/x509/x509_obj.cpp
+++ b/src/cert/x509/x509_obj.cpp
@@ -16,8 +16,6 @@
#include <algorithm>
#include <memory>
-#include <stdio.h>
-
namespace Botan {
/*
@@ -29,7 +27,7 @@ X509_Object::X509_Object(DataSource& stream, const std::string& labels)
}
/*
-* Createa a generic X.509 object
+* Create a generic X.509 object
*/
X509_Object::X509_Object(const std::string& file, const std::string& labels)
{
@@ -38,6 +36,15 @@ X509_Object::X509_Object(const std::string& file, const std::string& labels)
}
/*
+* Create a generic X.509 object
+*/
+X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels)
+ {
+ DataSource_Memory stream(&vec[0], vec.size());
+ init(stream, labels);
+ }
+
+/*
* Read a PEM or BER X.509 object
*/
void X509_Object::init(DataSource& in, const std::string& labels)
@@ -99,7 +106,7 @@ void X509_Object::encode(Pipe& out, X509_Encoding encoding) const
/*
* Return a BER encoded X.509 object
*/
-MemoryVector<byte> X509_Object::BER_encode() const
+std::vector<byte> X509_Object::BER_encode() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -109,7 +116,7 @@ MemoryVector<byte> X509_Object::BER_encode() const
.encode(sig_algo)
.encode(sig, BIT_STRING)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
@@ -123,7 +130,7 @@ std::string X509_Object::PEM_encode() const
/*
* Return the TBS data
*/
-MemoryVector<byte> X509_Object::tbs_data() const
+std::vector<byte> X509_Object::tbs_data() const
{
return ASN1::put_in_sequence(tbs_bits);
}
@@ -131,7 +138,7 @@ MemoryVector<byte> X509_Object::tbs_data() const
/*
* Return the signature of this object
*/
-MemoryVector<byte> X509_Object::signature() const
+std::vector<byte> X509_Object::signature() const
{
return sig;
}
@@ -170,7 +177,7 @@ std::string X509_Object::hash_used_for_signature() const
*/
bool X509_Object::check_signature(const Public_Key* pub_key) const
{
- std::auto_ptr<const Public_Key> key(pub_key);
+ std::unique_ptr<Public_Key> key(pub_key);
return check_signature(*key);
}
@@ -196,7 +203,6 @@ bool X509_Object::check_signature(const Public_Key& pub_key) const
}
catch(std::exception& e)
{
- printf("Failure during validation %s\n", e.what());
return false;
}
}
@@ -204,10 +210,10 @@ bool X509_Object::check_signature(const Public_Key& pub_key) const
/*
* Apply the X.509 SIGNED macro
*/
-MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer,
+std::vector<byte> X509_Object::make_signed(PK_Signer* signer,
RandomNumberGenerator& rng,
const AlgorithmIdentifier& algo,
- const MemoryRegion<byte>& tbs_bits)
+ const secure_vector<byte>& tbs_bits)
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -215,7 +221,7 @@ MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer,
.encode(algo)
.encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
diff --git a/src/cert/x509/x509_obj.h b/src/cert/x509/x509_obj.h
index e46e72ce3..e91389acf 100644
--- a/src/cert/x509/x509_obj.h
+++ b/src/cert/x509/x509_obj.h
@@ -27,12 +27,12 @@ class BOTAN_DLL X509_Object
* The underlying data that is to be or was signed
* @return data that is or was signed
*/
- MemoryVector<byte> tbs_data() const;
+ std::vector<byte> tbs_data() const;
/**
* @return signature on tbs_data()
*/
- MemoryVector<byte> signature() const;
+ std::vector<byte> signature() const;
/**
* @return signature algorithm that was used to generate signature
@@ -52,10 +52,10 @@ class BOTAN_DLL X509_Object
* @param tbs the tbs bits to be signed
* @return signed X509 object
*/
- static MemoryVector<byte> make_signed(class PK_Signer* signer,
- RandomNumberGenerator& rng,
- const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& tbs);
+ static std::vector<byte> make_signed(class PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& tbs);
/**
* Check the signature on this data
@@ -75,7 +75,7 @@ class BOTAN_DLL X509_Object
/**
* @return BER encoding of this
*/
- MemoryVector<byte> BER_encode() const;
+ std::vector<byte> BER_encode() const;
/**
* @return PEM encoding of this
@@ -95,15 +95,17 @@ class BOTAN_DLL X509_Object
protected:
X509_Object(DataSource& src, const std::string& pem_labels);
X509_Object(const std::string& file, const std::string& pem_labels);
+ X509_Object(const std::vector<byte>& vec, const std::string& labels);
void do_decode();
X509_Object() {}
AlgorithmIdentifier sig_algo;
- MemoryVector<byte> tbs_bits, sig;
+ std::vector<byte> tbs_bits, sig;
private:
virtual void force_decode() = 0;
void init(DataSource&, const std::string&);
void decode_info(DataSource&);
+
std::vector<std::string> PEM_labels_allowed;
std::string PEM_label_pref;
};
diff --git a/src/cert/x509/x509cert.cpp b/src/cert/x509/x509cert.cpp
index 52115a1a8..d757c2b58 100644
--- a/src/cert/x509/x509cert.cpp
+++ b/src/cert/x509/x509cert.cpp
@@ -30,12 +30,8 @@ std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
{
std::vector<std::string> out;
- std::vector<std::string>::const_iterator i = in.begin();
- while(i != in.end())
- {
+ for(auto i = in.begin(); i != in.end(); ++i)
out.push_back(OIDS::lookup(OID(*i)));
- ++i;
- }
return out;
}
@@ -62,6 +58,16 @@ X509_Certificate::X509_Certificate(const std::string& in) :
}
/*
+* X509_Certificate Constructor
+*/
+X509_Certificate::X509_Certificate(const std::vector<byte>& in) :
+ X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
+ {
+ self_signed = false;
+ do_decode();
+ }
+
+/*
* Decode the TBSCertificate data
*/
void X509_Certificate::force_decode()
@@ -87,7 +93,7 @@ void X509_Certificate::force_decode()
.decode(dn_subject);
if(version > 2)
- throw Decoding_Error("Unknown X.509 cert version " + Botan::to_string(version));
+ throw Decoding_Error("Unknown X.509 cert version " + std::to_string(version));
if(sig_algo != sig_algo_inner)
throw Decoding_Error("Algorithm identifier mismatch");
@@ -101,7 +107,7 @@ void X509_Certificate::force_decode()
throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
public_key.type_tag, public_key.class_tag);
- MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id;
+ std::vector<byte> v2_issuer_key_id, v2_subject_key_id;
tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
@@ -133,7 +139,7 @@ void X509_Certificate::force_decode()
subject.add("X509.Certificate.public_key",
PEM_Code::encode(
- ASN1::put_in_sequence(public_key.value),
+ ASN1::put_in_sequence(unlock(public_key.value)),
"PUBLIC KEY"
)
);
@@ -253,7 +259,7 @@ std::vector<std::string> X509_Certificate::policies() const
/*
* Return the authority key id
*/
-MemoryVector<byte> X509_Certificate::authority_key_id() const
+std::vector<byte> X509_Certificate::authority_key_id() const
{
return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
}
@@ -261,7 +267,7 @@ MemoryVector<byte> X509_Certificate::authority_key_id() const
/*
* Return the subject key id
*/
-MemoryVector<byte> X509_Certificate::subject_key_id() const
+std::vector<byte> X509_Certificate::subject_key_id() const
{
return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
}
@@ -269,7 +275,7 @@ MemoryVector<byte> X509_Certificate::subject_key_id() const
/*
* Return the certificate serial number
*/
-MemoryVector<byte> X509_Certificate::serial_number() const
+std::vector<byte> X509_Certificate::serial_number() const
{
return subject.get1_memvec("X509.Certificate.serial");
}
@@ -290,6 +296,50 @@ X509_DN X509_Certificate::subject_dn() const
return create_dn(subject);
}
+namespace {
+
+bool cert_subject_dns_match(const std::string& name,
+ const std::vector<std::string>& cert_names)
+ {
+ for(size_t i = 0; i != cert_names.size(); ++i)
+ {
+ const std::string cn = cert_names[i];
+
+ if(cn == name)
+ return true;
+
+ /*
+ * Possible wildcard match. We only support the most basic form of
+ * cert wildcarding ala RFC 2595
+ */
+ if(cn.size() > 2 && cn[0] == '*' && cn[1] == '.' && name.size() > cn.size())
+ {
+ const std::string base = cn.substr(1, std::string::npos);
+
+ if(name.compare(name.size() - base.size(), base.size(), base) == 0)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
+
+bool X509_Certificate::matches_dns_name(const std::string& name) const
+ {
+ if(name == "")
+ return false;
+
+ if(cert_subject_dns_match(name, subject_info("DNS")))
+ return true;
+
+ if(cert_subject_dns_match(name, subject_info("Name")))
+ return true;
+
+ return false;
+ }
+
/*
* Compare two certificates for equality
*/
@@ -302,6 +352,24 @@ bool X509_Certificate::operator==(const X509_Certificate& other) const
subject == other.subject);
}
+bool X509_Certificate::operator<(const X509_Certificate& other) const
+ {
+ /* If signature values are not equal, sort by lexicographic ordering of that */
+ if(sig != other.sig)
+ {
+ if(sig < other.sig)
+ return true;
+ return false;
+ }
+
+ /*
+ * same signatures, highly unlikely case, revert to compare
+ * of entire contents
+ */
+
+ return to_string() < other.to_string();
+ }
+
/*
* X.509 Certificate Comparison
*/
@@ -323,7 +391,7 @@ std::string X509_Certificate::to_string() const
"DNS",
"URI",
"PKIX.XMPPAddr",
- 0 };
+ nullptr };
std::ostringstream out;
@@ -419,24 +487,15 @@ std::string X509_Certificate::to_string() const
*/
X509_DN create_dn(const Data_Store& info)
{
- class DN_Matcher : public Data_Store::Matcher
+ auto names = info.search_for(
+ [](const std::string& key, const std::string&)
{
- public:
- bool operator()(const std::string& key, const std::string&) const
- {
- if(key.find("X520.") != std::string::npos)
- return true;
- return false;
- }
- };
-
- std::multimap<std::string, std::string> names =
- info.search_with(DN_Matcher());
+ return (key.find("X520.") != std::string::npos);
+ });
X509_DN dn;
- std::multimap<std::string, std::string>::iterator i;
- for(i = names.begin(); i != names.end(); ++i)
+ for(auto i = names.begin(); i != names.end(); ++i)
dn.add_attribute(i->first, i->second);
return dn;
@@ -447,32 +506,18 @@ X509_DN create_dn(const Data_Store& info)
*/
AlternativeName create_alt_name(const Data_Store& info)
{
- class AltName_Matcher : public Data_Store::Matcher
+ auto names = info.search_for(
+ [](const std::string& key, const std::string&)
{
- public:
- bool operator()(const std::string& key, const std::string&) const
- {
- for(size_t i = 0; i != matches.size(); ++i)
- if(key.compare(matches[i]) == 0)
- return true;
- return false;
- }
-
- AltName_Matcher(const std::string& match_any_of)
- {
- matches = split_on(match_any_of, '/');
- }
- private:
- std::vector<std::string> matches;
- };
-
- std::multimap<std::string, std::string> names =
- info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
+ return (key == "RFC822" ||
+ key == "DNS" ||
+ key == "URI" ||
+ key == "IP");
+ });
AlternativeName alt_name;
- std::multimap<std::string, std::string>::iterator i;
- for(i = names.begin(); i != names.end(); ++i)
+ for(auto i = names.begin(); i != names.end(); ++i)
alt_name.add_attribute(i->first, i->second);
return alt_name;
diff --git a/src/cert/x509/x509cert.h b/src/cert/x509/x509cert.h
index 6a4fd6959..e204fb274 100644
--- a/src/cert/x509/x509cert.h
+++ b/src/cert/x509/x509cert.h
@@ -85,19 +85,19 @@ class BOTAN_DLL X509_Certificate : public X509_Object
* Get the serial number of this certificate.
* @return certificates serial number
*/
- MemoryVector<byte> serial_number() const;
+ std::vector<byte> serial_number() const;
/**
* Get the DER encoded AuthorityKeyIdentifier of this certificate.
* @return DER encoded AuthorityKeyIdentifier
*/
- MemoryVector<byte> authority_key_id() const;
+ std::vector<byte> authority_key_id() const;
/**
* Get the DER encoded SubjectKeyIdentifier of this certificate.
* @return DER encoded SubjectKeyIdentifier
*/
- MemoryVector<byte> subject_key_id() const;
+ std::vector<byte> subject_key_id() const;
/**
* Check whether this certificate is self signed.
@@ -148,12 +148,24 @@ class BOTAN_DLL X509_Certificate : public X509_Object
std::string to_string() const;
/**
+ * Check if a certain DNS name matches up with the information in
+ * the cert
+ */
+ bool matches_dns_name(const std::string& name) const;
+
+ /**
* Check to certificates for equality.
* @return true both certificates are (binary) equal
*/
bool operator==(const X509_Certificate& other) const;
/**
+ * Impose an arbitrary (but consistent) ordering
+ * @return true if this is less than other by some unspecified criteria
+ */
+ bool operator<(const X509_Certificate& other) const;
+
+ /**
* Create a certificate from a data source providing the DER or
* PEM encoded certificate.
* @param source the data source
@@ -166,6 +178,9 @@ class BOTAN_DLL X509_Certificate : public X509_Object
* @param filename the name of the certificate file
*/
X509_Certificate(const std::string& filename);
+
+ X509_Certificate(const std::vector<byte>& in);
+
private:
void force_decode();
friend class X509_CA;
diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp
index 345df1fe0..8a27fdbde 100644
--- a/src/cert/x509/x509opt.cpp
+++ b/src/cert/x509/x509opt.cpp
@@ -8,7 +8,7 @@
#include <botan/x509self.h>
#include <botan/oids.h>
#include <botan/parsing.h>
-#include <botan/time.h>
+#include <chrono>
namespace Botan {
@@ -78,16 +78,16 @@ void X509_Cert_Options::sanity_check() const
* Initialize the certificate options
*/
X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts,
- u32bit expiration_time_in_seconds)
+ u32bit expiration_time)
{
is_CA = false;
path_limit = 0;
constraints = NO_CONSTRAINTS;
- const u64bit now = system_time();
+ auto now = std::chrono::system_clock::now();
start = X509_Time(now);
- end = X509_Time(now + expiration_time_in_seconds);
+ end = X509_Time(now + std::chrono::seconds(expiration_time));
if(initial_opts == "")
return;
diff --git a/src/cert/x509/x509path.cpp b/src/cert/x509/x509path.cpp
index fcf27841d..1d0667f85 100644
--- a/src/cert/x509/x509path.cpp
+++ b/src/cert/x509/x509path.cpp
@@ -9,8 +9,8 @@
#include <botan/parsing.h>
#include <botan/pubkey.h>
#include <botan/oids.h>
-#include <botan/time.h>
#include <algorithm>
+#include <chrono>
#include <memory>
namespace Botan {
diff --git a/src/cert/x509/x509path.h b/src/cert/x509/x509path.h
index 18129a236..fc784d429 100644
--- a/src/cert/x509/x509path.h
+++ b/src/cert/x509/x509path.h
@@ -10,7 +10,12 @@
#include <botan/x509cert.h>
#include <botan/certstor.h>
+<<<<<<< variant A
#include <set>
+>>>>>>> variant B
+#include <functional>
+####### Ancestor
+======= end
namespace Botan {
diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp
index a2f89159f..c13772382 100644
--- a/src/cert/x509/x509self.cpp
+++ b/src/cert/x509/x509self.cpp
@@ -53,8 +53,8 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
opts.sanity_check();
- MemoryVector<byte> pub_key = X509::BER_encode(key);
- std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
+ std::vector<byte> pub_key = X509::BER_encode(key);
+ std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
load_info(opts, subject_dn, subject_alt);
Key_Constraints constraints;
@@ -99,8 +99,8 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
opts.sanity_check();
- MemoryVector<byte> pub_key = X509::BER_encode(key);
- std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
+ std::vector<byte> pub_key = X509::BER_encode(key);
+ std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
load_info(opts, subject_dn, subject_alt);
const size_t PKCS10_VERSION = 0;
@@ -134,7 +134,7 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
tbs_req.encode(
Attribute("PKCS9.ChallengePassword",
- DER_Encoder().encode(challenge).get_contents()
+ DER_Encoder().encode(challenge).get_contents_unlocked()
)
);
}
@@ -145,20 +145,17 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
.start_cons(SEQUENCE)
.encode(extensions)
.end_cons()
- .get_contents()
+ .get_contents_unlocked()
)
)
.end_explicit()
.end_cons();
- DataSource_Memory source(
- X509_Object::make_signed(signer.get(),
- rng,
- sig_algo,
- tbs_req.get_contents())
- );
+ const std::vector<byte> req =
+ X509_Object::make_signed(signer.get(), rng, sig_algo,
+ tbs_req.get_contents());
- return PKCS10_Request(source);
+ return PKCS10_Request(req);
}
}
diff --git a/src/cms/cms_algo.cpp b/src/cms/cms_algo.cpp
index 3c245cc6f..6d768306b 100644
--- a/src/cms/cms_algo.cpp
+++ b/src/cms/cms_algo.cpp
@@ -23,10 +23,10 @@ namespace {
/*
* Wrap a key as specified in RFC 3217
*/
-SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
+secure_vector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
const std::string& cipher_name,
const SymmetricKey& kek,
- const SecureVector<byte>& input)
+ const secure_vector<byte>& input)
{
class Flip_Bytes : public Filter
{
@@ -44,9 +44,9 @@ SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
buf.clear();
}
- Flip_Bytes(const SecureVector<byte>& prefix) : buf(prefix) {}
+ Flip_Bytes(const secure_vector<byte>& prefix) : buf(prefix) {}
private:
- SecureVector<byte> buf;
+ secure_vector<byte> buf;
};
Algorithm_Factory& af = global_state().algorithm_factory();
@@ -78,7 +78,7 @@ SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
/*
* Wrap a CEK with a KEK
*/
-SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
+secure_vector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
const std::string& cipher,
const SymmetricKey& cek,
const SymmetricKey& kek)
@@ -98,7 +98,7 @@ SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
if(kek.length() != 16)
throw Encoding_Error("CMS: 128-bit KEKs must be used with " + cipher);
- SecureVector<byte> lcekpad;
+ secure_vector<byte> lcekpad;
lcekpad.push_back(static_cast<byte>(cek.length()));
lcekpad += cek.bits_of();
while(lcekpad.size() % 8)
@@ -113,7 +113,7 @@ SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
/*
* Encode the parameters for an encryption algo
*/
-SecureVector<byte> CMS_Encoder::encode_params(const std::string& cipher,
+secure_vector<byte> CMS_Encoder::encode_params(const std::string& cipher,
const SymmetricKey& key,
const InitializationVector& iv)
{
diff --git a/src/cms/cms_comp.cpp b/src/cms/cms_comp.cpp
index 3d9108e13..8ff46acea 100644
--- a/src/cms/cms_comp.cpp
+++ b/src/cms/cms_comp.cpp
@@ -37,13 +37,13 @@ void CMS_Encoder::compress(const std::string& algo)
Pipe pipe(compressor);
pipe.process_msg(data);
- SecureVector<byte> compressed = pipe.read_all();
+ secure_vector<byte> compressed = pipe.read_all();
DER_Encoder encoder;
encoder.start_cons(SEQUENCE).
encode(static_cast<size_t>(0)).
encode(AlgorithmIdentifier("Compression." + algo,
- MemoryVector<byte>())).
+ std::vector<byte>())).
raw_bytes(make_econtent(compressed, type)).
end_cons();
diff --git a/src/cms/cms_dalg.cpp b/src/cms/cms_dalg.cpp
index 2935f3070..96bdd5be3 100644
--- a/src/cms/cms_dalg.cpp
+++ b/src/cms/cms_dalg.cpp
@@ -20,7 +20,7 @@ namespace {
/*
* Compute the hash of some content
*/
-SecureVector<byte> hash_of(const SecureVector<byte>& content,
+secure_vector<byte> hash_of(const secure_vector<byte>& content,
const AlgorithmIdentifier& hash_algo,
std::string& hash_name)
{
@@ -28,7 +28,7 @@ SecureVector<byte> hash_of(const SecureVector<byte>& content,
Algorithm_Factory& af = global_state().algorithm_factory();
- std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
+ std::unique_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
return hash_fn->process(content);
}
@@ -51,10 +51,11 @@ std::vector<X509_Certificate> get_cert(BER_Decoder& signer_info,
iands.decode(issuer);
iands.decode(serial);
- found = store.get_certs(IandS_Match(issuer, BigInt::encode(serial)));
+ found = store.get_certs(
+ X509_Store_Search::by_issuer_and_serial(issuer, serial));
}
else if(id.type_tag == 0 && id.class_tag == CONSTRUCTED)
- found = store.get_certs(SKID_Match(id.value));
+ found = store.get_certs(X509_Store_Search::by_skid(id.value));
else
throw Decoding_Error("CMS: Unknown tag for cert identifier");
#endif
@@ -105,11 +106,11 @@ void read_orig_info(BER_Decoder& info, X509_Store& store)
/*
* Decode any Attributes, and check type
*/
-SecureVector<byte> decode_attributes(BER_Decoder& ber, const OID& type,
+secure_vector<byte> decode_attributes(BER_Decoder& ber, const OID& type,
bool& bad_attributes)
{
BER_Object obj = ber.get_next_object();
- SecureVector<byte> digest;
+ secure_vector<byte> digest;
bool got_digest = false;
bool got_content_type = false;
@@ -177,7 +178,7 @@ void CMS_Decoder::decode_layer()
{
size_t version;
AlgorithmIdentifier hash_algo;
- SecureVector<byte> digest;
+ secure_vector<byte> digest;
BER_Decoder hash_info = decoder.start_cons(SEQUENCE);
@@ -212,7 +213,7 @@ void CMS_Decoder::decode_layer()
while(signer_infos.more_items())
{
AlgorithmIdentifier sig_algo, hash_algo;
- SecureVector<byte> signature, digest;
+ secure_vector<byte> signature, digest;
size_t version;
BER_Decoder signer_info = BER::get_subsequence(signer_infos);
diff --git a/src/cms/cms_dec.h b/src/cms/cms_dec.h
index 8aa5c0edb..8c2057c2a 100644
--- a/src/cms/cms_dec.h
+++ b/src/cms/cms_dec.h
@@ -52,7 +52,7 @@ class BOTAN_DLL CMS_Decoder
std::vector<Private_Key*> keys;
OID type, next_type;
- SecureVector<byte> data;
+ secure_vector<byte> data;
Status status;
std::string info;
};
diff --git a/src/cms/cms_ealg.cpp b/src/cms/cms_ealg.cpp
index 4aee8afd8..4c3fd98fc 100644
--- a/src/cms/cms_ealg.cpp
+++ b/src/cms/cms_ealg.cpp
@@ -53,22 +53,22 @@ DER_Encoder& encode_si(DER_Encoder& der, const X509_Certificate& cert,
/*
* Compute the hash of some content
*/
-SecureVector<byte> hash_of(const SecureVector<byte>& content,
+secure_vector<byte> hash_of(const secure_vector<byte>& content,
const std::string& hash_name)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
+ std::unique_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
return hash_fn->process(content);
}
/*
* Encode Attributes containing info on content
*/
-SecureVector<byte> encode_attr(const SecureVector<byte>& data,
+secure_vector<byte> encode_attr(const secure_vector<byte>& data,
const std::string& type,
const std::string& hash)
{
- SecureVector<byte> digest = hash_of(data, hash);
+ secure_vector<byte> digest = hash_of(data, hash);
DER_Encoder encoder;
encoder.encode(OIDS::lookup(type));
@@ -96,7 +96,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
{
const std::string cipher = choose_algo(user_cipher, "TripleDES");
- std::auto_ptr<Public_Key> key(to.subject_public_key());
+ std::unique_ptr<Public_Key> key(to.subject_public_key());
const std::string algo = key->algo_name();
Key_Constraints constraints = to.constraints();
@@ -198,7 +198,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
const std::string cipher = choose_algo(user_cipher, "TripleDES");
SymmetricKey cek = setup_key(rng, cipher);
- SecureVector<byte> kek_id; // FIXME: ?
+ secure_vector<byte> kek_id; // FIXME: ?
DER_Encoder encoder;
@@ -244,7 +244,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator&,
/*
* Encrypt the content with the chosen key/cipher
*/
-SecureVector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng,
+secure_vector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng,
const SymmetricKey& key,
const std::string& cipher_name)
{
@@ -297,9 +297,9 @@ void CMS_Encoder::sign(const X509_Certificate& cert,
AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding),
AlgorithmIdentifier::USE_NULL_PARAM);
- SecureVector<byte> signed_attr = encode_attr(data, type, hash);
+ secure_vector<byte> signed_attr = encode_attr(data, type, hash);
signer.update(signed_attr);
- SecureVector<byte> signature = signer.signature(rng);
+ secure_vector<byte> signature = signer.signature(rng);
signed_attr[0] = 0xA0;
const size_t SI_VERSION = cert.subject_key_id().size() ? 3 : 1;
diff --git a/src/cms/cms_enc.cpp b/src/cms/cms_enc.cpp
index 1a45a6a46..58d7cabb6 100644
--- a/src/cms/cms_enc.cpp
+++ b/src/cms/cms_enc.cpp
@@ -36,7 +36,7 @@ void CMS_Encoder::set_data(const std::string& str)
/*
* Finalize and return the CMS encoded data
*/
-SecureVector<byte> CMS_Encoder::get_contents()
+secure_vector<byte> CMS_Encoder::get_contents()
{
DER_Encoder encoder;
@@ -72,7 +72,7 @@ std::string CMS_Encoder::PEM_contents()
/*
* Make an EncapsulatedContentInfo
*/
-SecureVector<byte> CMS_Encoder::make_econtent(const SecureVector<byte>& data,
+secure_vector<byte> CMS_Encoder::make_econtent(const secure_vector<byte>& data,
const std::string& type)
{
return DER_Encoder().start_cons(SEQUENCE).
diff --git a/src/cms/cms_enc.h b/src/cms/cms_enc.h
index 5dca838dd..c86dbe58e 100644
--- a/src/cms/cms_enc.h
+++ b/src/cms/cms_enc.h
@@ -47,7 +47,7 @@ class BOTAN_DLL CMS_Encoder
void compress(const std::string&);
static bool can_compress_with(const std::string&);
- SecureVector<byte> get_contents();
+ secure_vector<byte> get_contents();
std::string PEM_contents();
void set_data(const std::string&);
@@ -65,25 +65,25 @@ class BOTAN_DLL CMS_Encoder
const X509_Certificate&, Public_Key*,
const std::string&);
- SecureVector<byte> do_encrypt(RandomNumberGenerator& rng,
+ secure_vector<byte> do_encrypt(RandomNumberGenerator& rng,
const SymmetricKey&, const std::string&);
- static SecureVector<byte> make_econtent(const SecureVector<byte>&,
+ static secure_vector<byte> make_econtent(const secure_vector<byte>&,
const std::string&);
static SymmetricKey setup_key(RandomNumberGenerator& rng,
const std::string&);
- static SecureVector<byte> wrap_key(RandomNumberGenerator& rng,
+ static secure_vector<byte> wrap_key(RandomNumberGenerator& rng,
const std::string&,
const SymmetricKey&,
const SymmetricKey&);
- static SecureVector<byte> encode_params(const std::string&,
+ static secure_vector<byte> encode_params(const std::string&,
const SymmetricKey&,
const InitializationVector&);
- SecureVector<byte> data;
+ secure_vector<byte> data;
std::string type;
};
diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp
index 6a53a7a9a..719a3e8fa 100644
--- a/src/codec/base64/base64.cpp
+++ b/src/codec/base64/base64.cpp
@@ -92,11 +92,6 @@ std::string base64_encode(const byte input[],
return output;
}
-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,
@@ -226,11 +221,11 @@ size_t base64_decode(byte output[],
return base64_decode(output, &input[0], input.length(), ignore_ws);
}
-SecureVector<byte> base64_decode(const char input[],
+secure_vector<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);
+ secure_vector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4);
size_t written = base64_decode(&bin[0],
input,
@@ -241,7 +236,7 @@ SecureVector<byte> base64_decode(const char input[],
return bin;
}
-SecureVector<byte> base64_decode(const std::string& input,
+secure_vector<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 23a2558bd..9ea4143b7 100644
--- a/src/codec/base64/base64.h
+++ b/src/codec/base64/base64.h
@@ -46,7 +46,11 @@ std::string BOTAN_DLL base64_encode(const byte input[],
* @param input some input
* @return base64adecimal representation of input
*/
-std::string BOTAN_DLL base64_encode(const MemoryRegion<byte>& input);
+template<typename Alloc>
+std::string base64_encode(const std::vector<byte, Alloc>& input)
+ {
+ return base64_encode(&input[0], input.size());
+ }
/**
* Perform base64 decoding
@@ -104,7 +108,7 @@ size_t BOTAN_DLL base64_decode(byte output[],
exception if whitespace is encountered
* @return decoded base64 output
*/
-SecureVector<byte> BOTAN_DLL base64_decode(const char input[],
+secure_vector<byte> BOTAN_DLL base64_decode(const char input[],
size_t input_length,
bool ignore_ws = true);
@@ -115,7 +119,7 @@ SecureVector<byte> BOTAN_DLL base64_decode(const char input[],
exception if whitespace is encountered
* @return decoded base64 output
*/
-SecureVector<byte> BOTAN_DLL base64_decode(const std::string& input,
+secure_vector<byte> BOTAN_DLL base64_decode(const std::string& input,
bool ignore_ws = true);
}
diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp
index 41ba1298d..1fd32e2ed 100644
--- a/src/codec/hex/hex.cpp
+++ b/src/codec/hex/hex.cpp
@@ -34,12 +34,6 @@ void hex_encode(char output[],
}
}
-std::string hex_encode(const MemoryRegion<byte>& input,
- bool uppercase)
- {
- return hex_encode(&input[0], input.size(), uppercase);
- }
-
std::string hex_encode(const byte input[],
size_t input_length,
bool uppercase)
@@ -165,11 +159,11 @@ size_t hex_decode(byte output[],
return hex_decode(output, &input[0], input.length(), ignore_ws);
}
-SecureVector<byte> hex_decode(const char input[],
+secure_vector<byte> hex_decode(const char input[],
size_t input_length,
bool ignore_ws)
{
- SecureVector<byte> bin(1 + input_length / 2);
+ secure_vector<byte> bin(1 + input_length / 2);
size_t written = hex_decode(&bin[0],
input,
@@ -180,7 +174,7 @@ SecureVector<byte> hex_decode(const char input[],
return bin;
}
-SecureVector<byte> hex_decode(const std::string& input,
+secure_vector<byte> hex_decode(const std::string& input,
bool ignore_ws)
{
return hex_decode(&input[0], input.size(), ignore_ws);
diff --git a/src/codec/hex/hex.h b/src/codec/hex/hex.h
index 40930e808..bdb5e5365 100644
--- a/src/codec/hex/hex.h
+++ b/src/codec/hex/hex.h
@@ -42,8 +42,12 @@ std::string BOTAN_DLL hex_encode(const byte input[],
* @param uppercase should output be upper or lower case?
* @return hexadecimal representation of input
*/
-std::string BOTAN_DLL hex_encode(const MemoryRegion<byte>& input,
- bool uppercase = true);
+template<typename Alloc>
+std::string hex_encode(const std::vector<byte, Alloc>& input,
+ bool uppercase = true)
+ {
+ return hex_encode(&input[0], input.size(), uppercase);
+ }
/**
* Perform hex decoding
@@ -98,7 +102,7 @@ size_t BOTAN_DLL hex_decode(byte output[],
exception if whitespace is encountered
* @return decoded hex output
*/
-SecureVector<byte> BOTAN_DLL hex_decode(const char input[],
+secure_vector<byte> BOTAN_DLL hex_decode(const char input[],
size_t input_length,
bool ignore_ws = true);
@@ -109,8 +113,8 @@ SecureVector<byte> BOTAN_DLL hex_decode(const char input[],
exception if whitespace is encountered
* @return decoded hex output
*/
-SecureVector<byte> BOTAN_DLL hex_decode(const std::string& input,
- bool ignore_ws = true);
+secure_vector<byte> BOTAN_DLL hex_decode(const std::string& input,
+ bool ignore_ws = true);
}
diff --git a/src/codec/openpgp/openpgp.cpp b/src/codec/openpgp/openpgp.cpp
index ab9673689..7bd811a2f 100644
--- a/src/codec/openpgp/openpgp.cpp
+++ b/src/codec/openpgp/openpgp.cpp
@@ -67,7 +67,7 @@ std::string PGP_encode(const byte input[], size_t length,
/*
* OpenPGP Base64 decoding
*/
-SecureVector<byte> PGP_decode(DataSource& source,
+secure_vector<byte> PGP_decode(DataSource& source,
std::string& label,
std::map<std::string, std::string>& headers)
{
@@ -136,7 +136,7 @@ SecureVector<byte> PGP_decode(DataSource& source,
}
Pipe base64(new Base64_Decoder,
- new Fork(0,
+ new Fork(nullptr,
new Chain(new Hash_Filter(new CRC24),
new Base64_Encoder)
)
@@ -186,7 +186,7 @@ SecureVector<byte> PGP_decode(DataSource& source,
/*
* OpenPGP Base64 decoding
*/
-SecureVector<byte> PGP_decode(DataSource& source, std::string& label)
+secure_vector<byte> PGP_decode(DataSource& source, std::string& label)
{
std::map<std::string, std::string> ignored;
return PGP_decode(source, label, ignored);
diff --git a/src/codec/openpgp/openpgp.h b/src/codec/openpgp/openpgp.h
index 0cd77d53a..de56155f2 100644
--- a/src/codec/openpgp/openpgp.h
+++ b/src/codec/openpgp/openpgp.h
@@ -42,7 +42,7 @@ BOTAN_DLL std::string PGP_encode(
* @param headers is set to any headers
* @return decoded output as raw binary
*/
-BOTAN_DLL SecureVector<byte> PGP_decode(
+BOTAN_DLL secure_vector<byte> PGP_decode(
DataSource& source,
std::string& label,
std::map<std::string, std::string>& headers);
@@ -52,7 +52,7 @@ BOTAN_DLL SecureVector<byte> PGP_decode(
* @param label is set to the human-readable label
* @return decoded output as raw binary
*/
-BOTAN_DLL SecureVector<byte> PGP_decode(
+BOTAN_DLL secure_vector<byte> PGP_decode(
DataSource& source,
std::string& label);
diff --git a/src/codec/pem/pem.cpp b/src/codec/pem/pem.cpp
index 005ec7310..03ec33440 100644
--- a/src/codec/pem/pem.cpp
+++ b/src/codec/pem/pem.cpp
@@ -28,22 +28,13 @@ std::string encode(const byte der[], size_t length, const std::string& label,
}
/*
-* PEM encode BER/DER-encoded objects
-*/
-std::string encode(const MemoryRegion<byte>& data, const std::string& label,
- size_t width)
- {
- return encode(&data[0], data.size(), label, width);
- }
-
-/*
* Decode PEM down to raw BER/DER
*/
-SecureVector<byte> decode_check_label(DataSource& source,
+secure_vector<byte> decode_check_label(DataSource& source,
const std::string& label_want)
{
std::string label_got;
- SecureVector<byte> ber = decode(source, label_got);
+ secure_vector<byte> ber = decode(source, label_got);
if(label_got != label_want)
throw Decoding_Error("PEM: Label mismatch, wanted " + label_want +
", got " + label_got);
@@ -53,7 +44,7 @@ SecureVector<byte> decode_check_label(DataSource& source,
/*
* Decode PEM down to raw BER/DER
*/
-SecureVector<byte> decode(DataSource& source, std::string& label)
+secure_vector<byte> decode(DataSource& source, std::string& label)
{
const size_t RANDOM_CHAR_LIMIT = 8;
@@ -110,6 +101,19 @@ SecureVector<byte> decode(DataSource& source, std::string& label)
return base64.read_all();
}
+secure_vector<byte> decode_check_label(const std::string& pem,
+ const std::string& label_want)
+ {
+ DataSource_Memory src(pem);
+ return decode_check_label(src, label_want);
+ }
+
+secure_vector<byte> decode(const std::string& pem, std::string& label)
+ {
+ DataSource_Memory src(pem);
+ return decode(src, label);
+ }
+
/*
* Search for a PEM signature
*/
@@ -118,7 +122,7 @@ bool matches(DataSource& source, const std::string& extra,
{
const std::string PEM_HEADER = "-----BEGIN " + extra;
- SecureVector<byte> search_buf(search_range);
+ secure_vector<byte> search_buf(search_range);
size_t got = source.peek(&search_buf[0], search_buf.size(), 0);
if(got < PEM_HEADER.length())
diff --git a/src/codec/pem/pem.h b/src/codec/pem/pem.h
index d15bfe978..6c33c642d 100644
--- a/src/codec/pem/pem.h
+++ b/src/codec/pem/pem.h
@@ -14,18 +14,69 @@ namespace Botan {
namespace PEM_Code {
-/*
-* PEM Encoding/Decoding
+/**
+* Encode some binary data in PEM format
+*/
+BOTAN_DLL std::string encode(const byte data[],
+ size_t data_len,
+ const std::string& label,
+ size_t line_width = 64);
+
+/**
+* Encode some binary data in PEM format
+*/
+inline std::string encode(const std::vector<byte>& data,
+ const std::string& label,
+ size_t line_width = 64)
+ {
+ return encode(&data[0], data.size(), label, line_width);
+ }
+
+/**
+* Encode some binary data in PEM format
+*/
+inline std::string encode(const secure_vector<byte>& data,
+ const std::string& label,
+ size_t line_width = 64)
+ {
+ return encode(&data[0], data.size(), label, line_width);
+ }
+
+/**
+* Decode PEM data
+* @param label is set to the PEM label found for later inspection
*/
-BOTAN_DLL std::string encode(const byte[], size_t,
- const std::string&, size_t = 64);
-BOTAN_DLL std::string encode(const MemoryRegion<byte>&,
- const std::string&, size_t = 64);
+BOTAN_DLL secure_vector<byte> decode(DataSource& pem,
+ std::string& label);
-BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
-BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&,
- const std::string&);
-BOTAN_DLL bool matches(DataSource&, const std::string& = "",
+/**
+* Decode PEM data
+* @param label is set to the PEM label found for later inspection
+*/
+BOTAN_DLL secure_vector<byte> decode(const std::string& pem,
+ std::string& label);
+
+/**
+* Decode PEM data
+* @param label is what we expect the label to be
+*/
+BOTAN_DLL secure_vector<byte> decode_check_label(
+ DataSource& pem,
+ const std::string& label);
+
+/**
+* Decode PEM data
+* @param label is what we expect the label to be
+*/
+BOTAN_DLL secure_vector<byte> decode_check_label(
+ const std::string& pem,
+ const std::string& label);
+
+/**
+* Heuristic test for PEM data.
+*/
+BOTAN_DLL bool matches(DataSource& source,
+ const std::string& extra = "",
size_t search_range = 4096);
}
diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp
index 4d46f6b61..1adee90e8 100644
--- a/src/constructs/aont/package.cpp
+++ b/src/constructs/aont/package.cpp
@@ -37,7 +37,7 @@ void aont_package(RandomNumberGenerator& rng,
// Set K0 (the all zero key)
cipher->set_key(SymmetricKey(all_zeros));
- SecureVector<byte> buf(BLOCK_SIZE);
+ secure_vector<byte> buf(BLOCK_SIZE);
const size_t blocks =
(input_len + BLOCK_SIZE - 1) / BLOCK_SIZE;
@@ -57,13 +57,13 @@ void aont_package(RandomNumberGenerator& rng,
for(size_t j = 0; j != sizeof(i); ++j)
buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
- cipher->encrypt(buf);
+ cipher->encrypt(&buf[0]);
- xor_buf(final_block, buf, BLOCK_SIZE);
+ xor_buf(&final_block[0], &buf[0], BLOCK_SIZE);
}
// XOR the random package key into the final block
- xor_buf(final_block, package_key.begin(), BLOCK_SIZE);
+ xor_buf(&final_block[0], package_key.begin(), BLOCK_SIZE);
}
void aont_unpackage(BlockCipher* cipher,
@@ -83,8 +83,8 @@ void aont_unpackage(BlockCipher* cipher,
cipher->set_key(SymmetricKey(all_zeros));
- SecureVector<byte> package_key(BLOCK_SIZE);
- SecureVector<byte> buf(BLOCK_SIZE);
+ secure_vector<byte> package_key(BLOCK_SIZE);
+ secure_vector<byte> buf(BLOCK_SIZE);
// Copy the package key (masked with the block hashes)
copy_mem(&package_key[0],
@@ -105,9 +105,9 @@ void aont_unpackage(BlockCipher* cipher,
for(size_t j = 0; j != sizeof(i); ++j)
buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
- cipher->encrypt(buf);
+ cipher->encrypt(&buf[0]);
- xor_buf(&package_key[0], buf, BLOCK_SIZE);
+ xor_buf(&package_key[0], &buf[0], BLOCK_SIZE);
}
Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key));
diff --git a/src/constructs/cryptobox/cryptobox.cpp b/src/constructs/cryptobox/cryptobox.cpp
index ab263c3e9..aa2369c6c 100644
--- a/src/constructs/cryptobox/cryptobox.cpp
+++ b/src/constructs/cryptobox/cryptobox.cpp
@@ -44,7 +44,7 @@ std::string encrypt(const byte input[], size_t input_len,
const std::string& passphrase,
RandomNumberGenerator& rng)
{
- SecureVector<byte> pbkdf_salt(PBKDF_SALT_LEN);
+ secure_vector<byte> pbkdf_salt(PBKDF_SALT_LEN);
rng.randomize(&pbkdf_salt[0], pbkdf_salt.size());
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
@@ -64,7 +64,7 @@ std::string encrypt(const byte input[], size_t input_len,
Pipe pipe(get_cipher("Serpent/CTR-BE", cipher_key, iv, ENCRYPTION),
new Fork(
- 0,
+ nullptr,
new MAC_Filter(new HMAC(new SHA_512),
mac_key, MAC_OUTPUT_LEN)));
@@ -79,10 +79,10 @@ std::string encrypt(const byte input[], size_t input_len,
*/
const size_t ciphertext_len = pipe.remaining(0);
- SecureVector<byte> out_buf(VERSION_CODE_LEN +
- PBKDF_SALT_LEN +
- MAC_OUTPUT_LEN +
- ciphertext_len);
+ std::vector<byte> out_buf(VERSION_CODE_LEN +
+ PBKDF_SALT_LEN +
+ MAC_OUTPUT_LEN +
+ ciphertext_len);
for(size_t i = 0; i != VERSION_CODE_LEN; ++i)
out_buf[i] = get_byte(i, CRYPTOBOX_VERSION_CODE);
@@ -100,7 +100,7 @@ std::string decrypt(const byte input[], size_t input_len,
const std::string& passphrase)
{
DataSource_Memory input_src(input, input_len);
- SecureVector<byte> ciphertext =
+ secure_vector<byte> ciphertext =
PEM_Code::decode_check_label(input_src,
"BOTAN CRYPTOBOX MESSAGE");
diff --git a/src/constructs/fpe_fe1/fpe_fe1.cpp b/src/constructs/fpe_fe1/fpe_fe1.cpp
index 91d328c17..b22d3a8df 100644
--- a/src/constructs/fpe_fe1/fpe_fe1.cpp
+++ b/src/constructs/fpe_fe1/fpe_fe1.cpp
@@ -84,7 +84,7 @@ class FPE_Encryptor
public:
FPE_Encryptor(const SymmetricKey& key,
const BigInt& n,
- const MemoryRegion<byte>& tweak);
+ const std::vector<byte>& tweak);
~FPE_Encryptor() { delete mac; }
@@ -92,17 +92,17 @@ class FPE_Encryptor
private:
MessageAuthenticationCode* mac;
- SecureVector<byte> mac_n_t;
+ std::vector<byte> mac_n_t;
};
FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key,
const BigInt& n,
- const MemoryRegion<byte>& tweak)
+ const std::vector<byte>& tweak)
{
mac = new HMAC(new SHA_256);
mac->set_key(key);
- SecureVector<byte> n_bin = BigInt::encode(n);
+ std::vector<byte> n_bin = BigInt::encode(n);
if(n_bin.size() > MAX_N_BYTES)
throw std::runtime_error("N is too large for FPE encryption");
@@ -113,12 +113,12 @@ FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key,
mac->update_be(static_cast<u32bit>(tweak.size()));
mac->update(&tweak[0], tweak.size());
- mac_n_t = mac->final();
+ mac_n_t = unlock(mac->final());
}
BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R)
{
- SecureVector<byte> r_bin = BigInt::encode(R);
+ secure_vector<byte> r_bin = BigInt::encode_locked(R);
mac->update(mac_n_t);
mac->update_be(static_cast<u32bit>(round_no));
@@ -126,7 +126,7 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R)
mac->update_be(static_cast<u32bit>(r_bin.size()));
mac->update(&r_bin[0], r_bin.size());
- SecureVector<byte> X = mac->final();
+ secure_vector<byte> X = mac->final();
return BigInt(&X[0], X.size());
}
@@ -137,7 +137,7 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R)
*/
BigInt fe1_encrypt(const BigInt& n, const BigInt& X0,
const SymmetricKey& key,
- const MemoryRegion<byte>& tweak)
+ const std::vector<byte>& tweak)
{
FPE_Encryptor F(key, n, tweak);
@@ -165,7 +165,7 @@ BigInt fe1_encrypt(const BigInt& n, const BigInt& X0,
*/
BigInt fe1_decrypt(const BigInt& n, const BigInt& X0,
const SymmetricKey& key,
- const MemoryRegion<byte>& tweak)
+ const std::vector<byte>& tweak)
{
FPE_Encryptor F(key, n, tweak);
diff --git a/src/constructs/fpe_fe1/fpe_fe1.h b/src/constructs/fpe_fe1/fpe_fe1.h
index da9a6bcb6..66e7f1cfa 100644
--- a/src/constructs/fpe_fe1/fpe_fe1.h
+++ b/src/constructs/fpe_fe1/fpe_fe1.h
@@ -24,7 +24,7 @@ namespace FPE {
*/
BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
- const MemoryRegion<byte>& tweak);
+ const std::vector<byte>& tweak);
/**
* Decrypt X from and onto the group Z_n using key and tweak
@@ -35,7 +35,7 @@ BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X,
*/
BigInt BOTAN_DLL fe1_decrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
- const MemoryRegion<byte>& tweak);
+ const std::vector<byte>& tweak);
}
diff --git a/src/constructs/rfc3394/rfc3394.cpp b/src/constructs/rfc3394/rfc3394.cpp
index b000873fd..cfe95f40b 100644
--- a/src/constructs/rfc3394/rfc3394.cpp
+++ b/src/constructs/rfc3394/rfc3394.cpp
@@ -32,25 +32,25 @@ BlockCipher* make_aes(size_t keylength,
}
-SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key,
- const SymmetricKey& kek,
- Algorithm_Factory& af)
+secure_vector<byte> rfc3394_keywrap(const secure_vector<byte>& key,
+ const SymmetricKey& kek,
+ Algorithm_Factory& af)
{
if(key.size() % 8 != 0)
throw std::invalid_argument("Bad input key size for NIST key wrap");
- std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af));
+ std::unique_ptr<BlockCipher> aes(make_aes(kek.length(), af));
aes->set_key(kek);
const size_t n = key.size() / 8;
- SecureVector<byte> R((n + 1) * 8);
- SecureVector<byte> A(16);
+ secure_vector<byte> R((n + 1) * 8);
+ secure_vector<byte> A(16);
for(size_t i = 0; i != 8; ++i)
A[i] = 0xA6;
- copy_mem(&R[8], key.begin(), key.size());
+ copy_mem(&R[8], &key[0], key.size());
for(size_t j = 0; j <= 5; ++j)
{
@@ -74,25 +74,25 @@ SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key,
return R;
}
-SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key,
+secure_vector<byte> rfc3394_keyunwrap(const secure_vector<byte>& key,
const SymmetricKey& kek,
Algorithm_Factory& af)
{
if(key.size() < 16 || key.size() % 8 != 0)
throw std::invalid_argument("Bad input key size for NIST key unwrap");
- std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af));
+ std::unique_ptr<BlockCipher> aes(make_aes(kek.length(), af));
aes->set_key(kek);
const size_t n = (key.size() - 8) / 8;
- SecureVector<byte> R(n * 8);
- SecureVector<byte> A(16);
+ secure_vector<byte> R(n * 8);
+ secure_vector<byte> A(16);
for(size_t i = 0; i != 8; ++i)
A[i] = key[i];
- copy_mem(&R[0], key.begin() + 8, key.size() - 8);
+ copy_mem(&R[0], &key[8], key.size() - 8);
for(size_t j = 0; j <= 5; ++j)
{
diff --git a/src/constructs/rfc3394/rfc3394.h b/src/constructs/rfc3394/rfc3394.h
index 645586ee2..febd5207e 100644
--- a/src/constructs/rfc3394/rfc3394.h
+++ b/src/constructs/rfc3394/rfc3394.h
@@ -23,7 +23,7 @@ class Algorithm_Factory;
* @param af an algorithm factory
* @return key encrypted under kek
*/
-SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key,
+secure_vector<byte> BOTAN_DLL rfc3394_keywrap(const secure_vector<byte>& key,
const SymmetricKey& kek,
Algorithm_Factory& af);
@@ -36,7 +36,7 @@ SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key,
* @param af an algorithm factory
* @return key decrypted under kek
*/
-SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key,
+secure_vector<byte> BOTAN_DLL rfc3394_keyunwrap(const secure_vector<byte>& key,
const SymmetricKey& kek,
Algorithm_Factory& af);
diff --git a/src/constructs/srp6/srp6.cpp b/src/constructs/srp6/srp6.cpp
index 287f0bdfb..f1927b648 100644
--- a/src/constructs/srp6/srp6.cpp
+++ b/src/constructs/srp6/srp6.cpp
@@ -1,6 +1,6 @@
/*
-* SRP-6a
-* (C) 2011 Jack Lloyd
+* SRP-6a (RFC 5054 compatatible)
+* (C) 2011,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -20,7 +20,7 @@ BigInt hash_seq(const std::string& hash_id,
const BigInt& in1,
const BigInt& in2)
{
- std::auto_ptr<HashFunction> hash_fn(
+ std::unique_ptr<HashFunction> hash_fn(
global_state().algorithm_factory().make_hash_function(hash_id));
hash_fn->update(BigInt::encode_1363(in1, pad_to));
@@ -29,54 +29,61 @@ BigInt hash_seq(const std::string& hash_id,
return BigInt::decode(hash_fn->final());
}
-BigInt hash_seq(const std::string& hash_id,
- size_t pad_to,
- const BigInt& in1,
- const BigInt& in2,
- const BigInt& in3)
- {
- std::auto_ptr<HashFunction> hash_fn(
- global_state().algorithm_factory().make_hash_function(hash_id));
-
- hash_fn->update(BigInt::encode_1363(in1, pad_to));
- hash_fn->update(BigInt::encode_1363(in2, pad_to));
- hash_fn->update(BigInt::encode_1363(in3, pad_to));
-
- return BigInt::decode(hash_fn->final());
- }
-
BigInt compute_x(const std::string& hash_id,
const std::string& identifier,
const std::string& password,
- const MemoryRegion<byte>& salt)
+ const std::vector<byte>& salt)
{
- std::auto_ptr<HashFunction> hash_fn(
+ std::unique_ptr<HashFunction> hash_fn(
global_state().algorithm_factory().make_hash_function(hash_id));
hash_fn->update(identifier);
hash_fn->update(":");
hash_fn->update(password);
- SecureVector<byte> inner_h = hash_fn->final();
+ secure_vector<byte> inner_h = hash_fn->final();
hash_fn->update(salt);
hash_fn->update(inner_h);
- SecureVector<byte> outer_h = hash_fn->final();
+ secure_vector<byte> outer_h = hash_fn->final();
return BigInt::decode(outer_h);
}
}
+std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
+ {
+ /*
+ This function assumes that only one 'standard' SRP parameter set has
+ been defined for a particular bitsize. As of this writing that is the case.
+ */
+ try
+ {
+ const std::string group_name = "modp/srp/" + std::to_string(N.bits());
+
+ DL_Group group(group_name);
+
+ if(group.get_p() == N && group.get_g() == g)
+ return group_name;
+
+ throw std::runtime_error("Unknown SRP params");
+ }
+ catch(...)
+ {
+ throw Invalid_Argument("Bad SRP group parameters");
+ }
+ }
+
std::pair<BigInt, SymmetricKey>
-SRP6_Client_Session:: step1(const std::string& identifier,
- const std::string& password,
- const std::string& group_id,
- const std::string& hash_id,
- const MemoryRegion<byte>& salt,
- const BigInt& B,
- RandomNumberGenerator& rng)
+srp6_client_agree(const std::string& identifier,
+ const std::string& password,
+ const std::string& group_id,
+ const std::string& hash_id,
+ const std::vector<byte>& salt,
+ const BigInt& B,
+ RandomNumberGenerator& rng)
{
DL_Group group(group_id);
const BigInt& g = group.get_g();
@@ -89,7 +96,7 @@ SRP6_Client_Session:: step1(const std::string& identifier,
BigInt k = hash_seq(hash_id, p_bytes, p, g);
- BigInt a(rng, p.bits() - 1);
+ BigInt a(rng, 256);
BigInt A = power_mod(g, a, p);
@@ -104,11 +111,11 @@ SRP6_Client_Session:: step1(const std::string& identifier,
return std::make_pair(A, Sk);
}
-BigInt SRP6_Client_Session::generate_verifier(const std::string& identifier,
- const std::string& password,
- const MemoryRegion<byte>& salt,
- const std::string& group_id,
- const std::string& hash_id)
+BigInt generate_srp6_verifier(const std::string& identifier,
+ const std::string& password,
+ const std::vector<byte>& salt,
+ const std::string& group_id,
+ const std::string& hash_id)
{
const BigInt x = compute_x(hash_id, identifier, password, salt);
@@ -129,7 +136,7 @@ BigInt SRP6_Server_Session::step1(const BigInt& v,
BigInt k = hash_seq(hash_id, p_bytes, p, g);
- BigInt b(rng, p.bits() - 1);
+ BigInt b(rng, 256);
B = (v*k + power_mod(g, b, p)) % p;
diff --git a/src/constructs/srp6/srp6.h b/src/constructs/srp6/srp6.h
index 01bd2a4c7..b34253d7a 100644
--- a/src/constructs/srp6/srp6.h
+++ b/src/constructs/srp6/srp6.h
@@ -1,6 +1,6 @@
/*
* SRP-6a (RFC 5054 compatatible)
-* (C) 2011 Jack Lloyd
+* (C) 2011,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -17,44 +17,43 @@
namespace Botan {
/**
-* Represents a SRP-6a client session
+* SRP6a Client side
+* @param username the username we are attempting login for
+* @param password the password we are attempting to use
+* @param group_id specifies the shared SRP group
+* @param hash_id specifies a secure hash function
+* @param salt is the salt value sent by the server
+* @param B is the server's public value
+* @param rng is a random number generator
+*
+* @return (A,K) the client public key and the shared secret key
*/
-class BOTAN_DLL SRP6_Client_Session
- {
- public:
+std::pair<BigInt,SymmetricKey>
+BOTAN_DLL srp6_client_agree(const std::string& username,
+ const std::string& password,
+ const std::string& group_id,
+ const std::string& hash_id,
+ const std::vector<byte>& salt,
+ const BigInt& B,
+ RandomNumberGenerator& rng);
- /**
- * Client side step 1
- * @param username the username we are attempting login for
- * @param password the password we are attempting to use
- * @param group_id specifies the shared SRP group
- * @param hash_id specifies a secure hash function
- * @param salt is the salt value sent by the server
- * @param B is the server's public value
- * @param rng is a random number generator
- *
- * @return (A,K) the client public key and the shared secret key
- */
- std::pair<BigInt,SymmetricKey> step1(const std::string& username,
- const std::string& password,
- const std::string& group_id,
- const std::string& hash_id,
- const MemoryRegion<byte>& salt,
- const BigInt& B,
- RandomNumberGenerator& rng);
+/**
+* Generate a new SRP-6 verifier
+* @param identifier a username or other client identifier
+* @param password the secret used to authenticate user
+* @param salt a randomly chosen value, at least 128 bits long
+*/
+BigInt BOTAN_DLL generate_srp6_verifier(const std::string& identifier,
+ const std::string& password,
+ const std::vector<byte>& salt,
+ const std::string& group_id,
+ const std::string& hash_id);
- /**
- * Generate a new SRP-6 verifier
- * @param identifier a username or other client identifier
- * @param password the secret used to authenticate user
- * @param salt a randomly chosen value, at least 128 bits long
- */
- static BigInt generate_verifier(const std::string& identifier,
- const std::string& password,
- const MemoryRegion<byte>& salt,
- const std::string& group_id,
- const std::string& hash_id);
- };
+/**
+* Return the group id for this SRP param set, or else thrown an
+* exception
+*/
+std::string BOTAN_DLL srp6_group_identifier(const BigInt& N, const BigInt& g);
/**
* Represents a SRP-6a server session
diff --git a/src/constructs/srp6/srp6_files.cpp b/src/constructs/srp6/srp6_files.cpp
index 2d685614f..4df2986f3 100644
--- a/src/constructs/srp6/srp6_files.cpp
+++ b/src/constructs/srp6/srp6_files.cpp
@@ -31,7 +31,7 @@ SRP6_Authenticator_File::SRP6_Authenticator_File(const std::string& filename)
std::string username = parts[0];
BigInt v = BigInt::decode(base64_decode(parts[1]));
- MemoryVector<byte> salt = base64_decode(parts[2]);
+ std::vector<byte> salt = unlock(base64_decode(parts[2]));
BigInt group_id_idx = BigInt::decode(base64_decode(parts[3]));
std::string group_id;
@@ -51,7 +51,7 @@ SRP6_Authenticator_File::SRP6_Authenticator_File(const std::string& filename)
bool SRP6_Authenticator_File::lookup_user(const std::string& username,
BigInt& v,
- MemoryVector<byte>& salt,
+ std::vector<byte>& salt,
std::string& group_id) const
{
std::map<std::string, SRP6_Data>::const_iterator i = entries.find(username);
diff --git a/src/constructs/srp6/srp6_files.h b/src/constructs/srp6/srp6_files.h
index 1def0fd51..4e0d3ff02 100644
--- a/src/constructs/srp6/srp6_files.h
+++ b/src/constructs/srp6/srp6_files.h
@@ -17,7 +17,7 @@ namespace Botan {
/**
* A GnuTLS compatible SRP6 authenticator file
*/
-class SRP6_Authenticator_File
+class BOTAN_DLL SRP6_Authenticator_File
{
public:
/**
@@ -28,7 +28,7 @@ class SRP6_Authenticator_File
bool lookup_user(const std::string& username,
BigInt& v,
- MemoryVector<byte>& salt,
+ std::vector<byte>& salt,
std::string& group_id) const;
private:
struct SRP6_Data
@@ -36,12 +36,12 @@ class SRP6_Authenticator_File
SRP6_Data() {}
SRP6_Data(const BigInt& v,
- const MemoryRegion<byte>& salt,
+ const std::vector<byte>& salt,
const std::string& group_id) :
v(v), salt(salt), group_id(group_id) {}
BigInt v;
- MemoryVector<byte> salt;
+ std::vector<byte> salt;
std::string group_id;
};
diff --git a/src/constructs/tss/tss.cpp b/src/constructs/tss/tss.cpp
index d0a18f534..e002084a1 100644
--- a/src/constructs/tss/tss.cpp
+++ b/src/constructs/tss/tss.cpp
@@ -150,7 +150,7 @@ RTSS_Share::split(byte M, byte N,
shares[i].contents.push_back(i+1);
// secret = S || H(S)
- SecureVector<byte> secret(S, S_len);
+ secure_vector<byte> secret(S, S + S_len);
secret += hash.process(S, S_len);
for(size_t i = 0; i != secret.size(); ++i)
@@ -178,7 +178,7 @@ RTSS_Share::split(byte M, byte N,
return shares;
}
-SecureVector<byte>
+secure_vector<byte>
RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares)
{
const size_t RTSS_HEADER_SIZE = 20;
@@ -205,13 +205,13 @@ RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares)
byte hash_id = shares[0].contents[16];
- std::auto_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id));
+ std::unique_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id));
if(shares[0].size() != secret_len + hash->output_length() + RTSS_HEADER_SIZE + 1)
throw Decoding_Error("Bad RTSS length field in header");
std::vector<byte> V(shares.size());
- SecureVector<byte> secret;
+ secure_vector<byte> secret;
for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i)
{
@@ -250,13 +250,13 @@ RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares)
throw Decoding_Error("Bad length in RTSS output");
hash->update(&secret[0], secret_len);
- SecureVector<byte> hash_check = hash->final();
+ secure_vector<byte> hash_check = hash->final();
if(!same_mem(&hash_check[0],
&secret[secret_len], hash->output_length()))
throw Decoding_Error("RTSS hash check failed");
- return SecureVector<byte>(&secret[0], secret_len);
+ return secure_vector<byte>(&secret[0], &secret[secret_len]);
}
}
diff --git a/src/constructs/tss/tss.h b/src/constructs/tss/tss.h
index 297c65971..4664af317 100644
--- a/src/constructs/tss/tss.h
+++ b/src/constructs/tss/tss.h
@@ -38,7 +38,7 @@ class BOTAN_DLL RTSS_Share
/**
* @param shares the list of shares
*/
- static SecureVector<byte>
+ static secure_vector<byte>
reconstruct(const std::vector<RTSS_Share>& shares);
RTSS_Share() {}
@@ -68,7 +68,7 @@ class BOTAN_DLL RTSS_Share
*/
bool initialized() const { return (contents.size() > 0); }
private:
- SecureVector<byte> contents;
+ secure_vector<byte> contents;
};
}
diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp
new file mode 100644
index 000000000..adb3a64fc
--- /dev/null
+++ b/src/credentials/credentials_manager.cpp
@@ -0,0 +1,149 @@
+/*
+* Credentials Manager
+* (C) 2011,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/credentials_manager.h>
+#include <botan/x509stor.h>
+
+namespace Botan {
+
+std::string Credentials_Manager::psk_identity_hint(const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+std::string Credentials_Manager::psk_identity(const std::string&,
+ const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+SymmetricKey Credentials_Manager::psk(const std::string&,
+ const std::string&,
+ const std::string& identity)
+ {
+ throw Internal_Error("No PSK set for identity " + identity);
+ }
+
+bool Credentials_Manager::attempt_srp(const std::string&,
+ const std::string&)
+ {
+ return false;
+ }
+
+std::string Credentials_Manager::srp_identifier(const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+std::string Credentials_Manager::srp_password(const std::string&,
+ const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+bool Credentials_Manager::srp_verifier(const std::string&,
+ const std::string&,
+ const std::string&,
+ std::string&,
+ BigInt&,
+ std::vector<byte>&,
+ bool)
+ {
+ return false;
+ }
+
+std::vector<X509_Certificate> Credentials_Manager::cert_chain(
+ const std::vector<std::string>&,
+ const std::string&,
+ const std::string&)
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+std::vector<X509_Certificate> Credentials_Manager::cert_chain_single_type(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context)
+ {
+ std::vector<std::string> cert_types;
+ cert_types.push_back(cert_key_type);
+ return cert_chain(cert_types, type, context);
+ }
+
+Private_Key* Credentials_Manager::private_key_for(const X509_Certificate&,
+ const std::string&,
+ const std::string&)
+ {
+ return nullptr;
+ }
+
+std::vector<X509_Certificate>
+Credentials_Manager::trusted_certificate_authorities(
+ const std::string&,
+ const std::string&)
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+void Credentials_Manager::verify_certificate_chain(
+ const std::string& type,
+ const std::string& purported_hostname,
+ const std::vector<X509_Certificate>& cert_chain)
+ {
+ if(cert_chain.empty())
+ throw std::invalid_argument("Certificate chain was empty");
+
+ if(purported_hostname != "" && !cert_chain[0].matches_dns_name(purported_hostname))
+ throw std::runtime_error("Certificate did not match hostname");
+
+#if 1
+ std::vector<X509_Certificate> CAs = trusted_certificate_authorities(type, purported_hostname);
+
+ X509_Store store;
+
+ for(size_t i = 0; i != CAs.size(); ++i)
+ store.add_cert(CAs[i], true);
+ for(size_t i = 0; i != cert_chain.size(); ++i)
+ store.add_cert(cert_chain[i]);
+
+ X509_Code result = store.validate_cert(cert_chain[0], X509_Store::TLS_SERVER);
+
+ if(CAs.empty())
+ {
+ if(result == CERT_ISSUER_NOT_FOUND)
+ return;
+ if(result == CANNOT_ESTABLISH_TRUST)
+ return;
+ }
+
+ if(result != VERIFIED)
+ throw std::runtime_error("Certificate did not validate, code " +
+ std::to_string(result));
+#else
+
+ // New X.509 API
+ const Certificate_Store& CAs =
+ trusted_certificate_authorities(type, purported_hostname);
+
+ Path_Validation_Result result =
+ x509_path_validate(cert_chain,
+ Path_Validation_Restrictions(),
+ store);
+
+ if(!result.successful_validation())
+ throw std::runtime_error("Certificate validation failure: " + result.as_string());
+
+ if(!CAs.certificate_known(result.trust_root())
+ throw std::runtime_error("Certificate chain roots in unknown/untrusted CA");
+#endif
+ }
+
+}
diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h
new file mode 100644
index 000000000..57ebd8b38
--- /dev/null
+++ b/src/credentials/credentials_manager.h
@@ -0,0 +1,153 @@
+/*
+* Credentials Manager
+* (C) 2011,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CREDENTIALS_MANAGER_H__
+#define BOTAN_CREDENTIALS_MANAGER_H__
+
+#include <botan/x509cert.h>
+#include <botan/symkey.h>
+#include <string>
+
+namespace Botan {
+
+class BigInt;
+
+/**
+* Interface for a credentials manager.
+*
+* A type is a fairly static value that represents the general nature
+* of the transaction occuring. Currently used values are "tls-client"
+* and "tls-server". Context represents a hostname, email address,
+* username, or other identifier.
+*/
+class BOTAN_DLL Credentials_Manager
+ {
+ public:
+ virtual ~Credentials_Manager() {}
+
+ virtual std::string psk_identity_hint(const std::string& type,
+ const std::string& context);
+
+ /**
+ * @param identity_hint was passed by the server (but may be empty)
+ * @return the PSK identity we want to use
+ */
+ virtual std::string psk_identity(const std::string& type,
+ const std::string& context,
+ const std::string& identity_hint);
+
+ /**
+ * @return the PSK used for identity, or throw an exception if no
+ * key exists
+ */
+ virtual SymmetricKey psk(const std::string& type,
+ const std::string& context,
+ const std::string& identity);
+
+ /**
+ * Return true if we should attempt SRP authentication
+ */
+ virtual bool attempt_srp(const std::string& type,
+ const std::string& context);
+
+ /**
+ * @return identifier for client-side SRP auth, if available
+ for this type/context. Should return empty string
+ if password auth not desired/available.
+ */
+ virtual std::string srp_identifier(const std::string& type,
+ const std::string& context);
+
+ /**
+ * @param identifier specifies what identifier we want the
+ * password for. This will be a value previously returned
+ * by srp_identifier.
+ * @return password for client-side SRP auth, if available
+ for this identifier/type/context.
+ */
+ virtual std::string srp_password(const std::string& type,
+ const std::string& context,
+ const std::string& identifier);
+
+ /**
+ * Retrieve SRP verifier parameters
+ */
+ virtual bool srp_verifier(const std::string& type,
+ const std::string& context,
+ const std::string& identifier,
+ std::string& group_name,
+ BigInt& verifier,
+ std::vector<byte>& salt,
+ bool generate_fake_on_unknown);
+
+ /**
+ * Return a cert chain we can use, ordered from leaf to root,
+ * or else an empty vector.
+ *
+ * It is assumed that the caller can get the private key of the
+ * leaf with private_key_for
+ *
+ * @param cert_key_types specifies the key types desired ("RSA",
+ * "DSA", "ECDSA", etc), or empty if there
+ * is no preference by the caller.
+ */
+ virtual std::vector<X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * Return a cert chain we can use, ordered from leaf to root,
+ * or else an empty vector.
+ *
+ * It is assumed that the caller can get the private key of the
+ * leaf with private_key_for
+ *
+ * @param cert_key_type specifies the type of key requested
+ * ("RSA", "DSA", "ECDSA", etc)
+ */
+ std::vector<X509_Certificate> cert_chain_single_type(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * Return a list of the certificates of CAs that we trust in this
+ * type/context.
+ */
+ virtual std::vector<X509_Certificate> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * Check the certificate chain is valid up to a trusted root, and
+ * optionally (if hostname != "") that the hostname given is
+ * consistent with the leaf certificate.
+ *
+ * This function should throw an exception derived from
+ * std::exception with an informative what() result if the
+ * certificate chain cannot be verified.
+ */
+ virtual void verify_certificate_chain(
+ const std::string& type,
+ const std::string& hostname,
+ const std::vector<X509_Certificate>& cert_chain);
+
+ /**
+ * @return private key associated with this certificate if we should
+ * use it with this context. cert was returned by cert_chain
+ * @note this object should retain ownership of the returned key;
+ * it should not be deleted by the caller.
+ */
+ virtual Private_Key* private_key_for(const X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context);
+ };
+
+}
+
+#endif
diff --git a/src/credentials/info.txt b/src/credentials/info.txt
new file mode 100644
index 000000000..689c4f1ae
--- /dev/null
+++ b/src/credentials/info.txt
@@ -0,0 +1,6 @@
+define CREDENTIALS_MANAGER
+
+<requires>
+x509cert
+x509store
+</requires>
diff --git a/src/engine/asm_engine/asm_engine.cpp b/src/engine/asm_engine/asm_engine.cpp
index 6d475136f..a43a3302d 100644
--- a/src/engine/asm_engine/asm_engine.cpp
+++ b/src/engine/asm_engine/asm_engine.cpp
@@ -40,7 +40,7 @@ Assembler_Engine::find_block_cipher(const SCAN_Name& request,
#endif
}
- return 0;
+ return nullptr;
}
HashFunction*
@@ -66,7 +66,7 @@ Assembler_Engine::find_hash(const SCAN_Name& request,
#endif
}
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/asm_engine/asm_engine.h b/src/engine/asm_engine/asm_engine.h
index bd82566d3..40fe5342f 100644
--- a/src/engine/asm_engine/asm_engine.h
+++ b/src/engine/asm_engine/asm_engine.h
@@ -23,7 +23,7 @@ class Assembler_Engine : public Engine
BlockCipher* find_block_cipher(const SCAN_Name&,
Algorithm_Factory&) const;
- HashFunction* find_hash(const SCAN_Name& reqeust,
+ HashFunction* find_hash(const SCAN_Name& request,
Algorithm_Factory&) const;
};
diff --git a/src/engine/core_engine/core_engine.h b/src/engine/core_engine/core_engine.h
index 5386991c3..983b75290 100644
--- a/src/engine/core_engine/core_engine.h
+++ b/src/engine/core_engine/core_engine.h
@@ -44,10 +44,10 @@ class Core_Engine : public Engine
StreamCipher* find_stream_cipher(const SCAN_Name&,
Algorithm_Factory&) const;
- HashFunction* find_hash(const SCAN_Name& reqeust,
+ HashFunction* find_hash(const SCAN_Name& request,
Algorithm_Factory&) const;
- MessageAuthenticationCode* find_mac(const SCAN_Name& reqeust,
+ MessageAuthenticationCode* find_mac(const SCAN_Name& request,
Algorithm_Factory&) const;
PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
diff --git a/src/engine/core_engine/core_modes.cpp b/src/engine/core_engine/core_modes.cpp
index 8a929e880..ffd8aa04f 100644
--- a/src/engine/core_engine/core_modes.cpp
+++ b/src/engine/core_engine/core_modes.cpp
@@ -111,7 +111,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
else
return new CTS_Decryption(block_cipher->clone());
#else
- return 0;
+ return nullptr;
#endif
}
@@ -123,7 +123,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
return new CBC_Decryption(block_cipher->clone(),
get_bc_pad(padding, "PKCS7"));
#else
- return 0;
+ return nullptr;
#endif
}
@@ -149,7 +149,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
else if(algo_info.size() == 2)
bits = to_u32bit(algo_info[1]);
else
- return 0;
+ return nullptr;
#if defined(BOTAN_HAS_CFB)
if(mode_name == "CFB")
@@ -172,7 +172,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
#endif
}
- return 0;
+ return nullptr;
}
/*
@@ -195,10 +195,10 @@ Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
if(!block_cipher)
- return 0;
+ return nullptr;
if(algo_parts.size() >= 4)
- return 0; // 4 part mode, not something we know about
+ return nullptr; // 4 part mode, not something we know about
if(algo_parts.size() < 2)
throw Lookup_Error("Cipher specification '" + algo_spec +
@@ -213,7 +213,7 @@ Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
if(mode == "ECB" && padding == "CTS")
- return 0;
+ return nullptr;
else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
throw Invalid_Algorithm_Name(algo_spec);
diff --git a/src/engine/core_engine/def_pk_ops.cpp b/src/engine/core_engine/def_pk_ops.cpp
index db418d5bc..23ba7722c 100644
--- a/src/engine/core_engine/def_pk_ops.cpp
+++ b/src/engine/core_engine/def_pk_ops.cpp
@@ -58,7 +58,7 @@ Core_Engine::get_encryption_op(const Public_Key& key) const
return new ElGamal_Encryption_Operation(*s);
#endif
- return 0;
+ return nullptr;
}
PK_Ops::Decryption*
@@ -74,7 +74,7 @@ Core_Engine::get_decryption_op(const Private_Key& key) const
return new ElGamal_Decryption_Operation(*s);
#endif
- return 0;
+ return nullptr;
}
PK_Ops::Key_Agreement*
@@ -90,7 +90,7 @@ Core_Engine::get_key_agreement_op(const Private_Key& key) const
return new ECDH_KA_Operation(*ecdh);
#endif
- return 0;
+ return nullptr;
}
PK_Ops::Signature*
@@ -127,7 +127,7 @@ Core_Engine::get_signature_op(const Private_Key& key) const
return new NR_Signature_Operation(*s);
#endif
- return 0;
+ return nullptr;
}
PK_Ops::Verification*
@@ -164,7 +164,7 @@ Core_Engine::get_verify_op(const Public_Key& key) const
return new NR_Verification_Operation(*s);
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/core_engine/lookup_block.cpp b/src/engine/core_engine/lookup_block.cpp
index c27a13237..a02c75daa 100644
--- a/src/engine/core_engine/lookup_block.cpp
+++ b/src/engine/core_engine/lookup_block.cpp
@@ -135,8 +135,12 @@ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request,
#endif
#if defined(BOTAN_HAS_CAMELLIA)
- if(request.algo_name() == "Camellia")
- return new Camellia;
+ if(request.algo_name() == "Camellia-128")
+ return new Camellia_128;
+ if(request.algo_name() == "Camellia-192")
+ return new Camellia_192;
+ if(request.algo_name() == "Camellia-256")
+ return new Camellia_256;
#endif
#if defined(BOTAN_HAS_CAST)
@@ -273,13 +277,13 @@ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request,
af.prototype_stream_cipher(request.arg(1));
if(!hash || !stream_cipher)
- return 0;
+ return nullptr;
return new Lion(hash->clone(), stream_cipher->clone(), block_size);
}
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/core_engine/lookup_hash.cpp b/src/engine/core_engine/lookup_hash.cpp
index f94a97864..9958d18b9 100644
--- a/src/engine/core_engine/lookup_hash.cpp
+++ b/src/engine/core_engine/lookup_hash.cpp
@@ -218,7 +218,7 @@ HashFunction* Core_Engine::find_hash(const SCAN_Name& request,
{
const HashFunction* hash = af.prototype_hash_function(request.arg(i));
if(!hash)
- return 0;
+ return nullptr;
hash_prototypes.push_back(hash);
}
@@ -232,7 +232,7 @@ HashFunction* Core_Engine::find_hash(const SCAN_Name& request,
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/core_engine/lookup_mac.cpp b/src/engine/core_engine/lookup_mac.cpp
index 9f322b399..32275b559 100644
--- a/src/engine/core_engine/lookup_mac.cpp
+++ b/src/engine/core_engine/lookup_mac.cpp
@@ -64,7 +64,7 @@ Core_Engine::find_mac(const SCAN_Name& request,
return new ANSI_X919_MAC(af.make_block_cipher("DES"));
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/core_engine/lookup_pbkdf.cpp b/src/engine/core_engine/lookup_pbkdf.cpp
index 9e9255f0a..2419f4373 100644
--- a/src/engine/core_engine/lookup_pbkdf.cpp
+++ b/src/engine/core_engine/lookup_pbkdf.cpp
@@ -46,7 +46,7 @@ PBKDF* Core_Engine::find_pbkdf(const SCAN_Name& algo_spec,
return new OpenPGP_S2K(af.make_hash_function(algo_spec.arg(0)));
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/core_engine/lookup_stream.cpp b/src/engine/core_engine/lookup_stream.cpp
index 5b4859c1a..50e246756 100644
--- a/src/engine/core_engine/lookup_stream.cpp
+++ b/src/engine/core_engine/lookup_stream.cpp
@@ -55,7 +55,7 @@ Core_Engine::find_stream_cipher(const SCAN_Name& request,
return new WiderWake_41_BE;
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/dyn_engine/dyn_engine.cpp b/src/engine/dyn_engine/dyn_engine.cpp
index b76544d0f..078ec4b83 100644
--- a/src/engine/dyn_engine/dyn_engine.cpp
+++ b/src/engine/dyn_engine/dyn_engine.cpp
@@ -21,7 +21,7 @@ extern "C" {
Dynamically_Loaded_Engine::Dynamically_Loaded_Engine(
const std::string& library_path) :
- engine(0)
+ engine(nullptr)
{
lib = new Dynamically_Loaded_Library(library_path);
@@ -35,7 +35,7 @@ Dynamically_Loaded_Engine::Dynamically_Loaded_Engine(
if(mod_version != 20101003)
throw std::runtime_error("Incompatible version in " +
library_path + " of " +
- to_string(mod_version));
+ std::to_string(mod_version));
creator_func creator =
lib->resolve<creator_func>("create_engine");
@@ -49,7 +49,7 @@ Dynamically_Loaded_Engine::Dynamically_Loaded_Engine(
catch(...)
{
delete lib;
- lib = 0;
+ lib = nullptr;
throw;
}
}
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
index 80712a2f8..d4f6885bc 100644
--- a/src/engine/engine.cpp
+++ b/src/engine/engine.cpp
@@ -13,79 +13,79 @@ BlockCipher*
Engine::find_block_cipher(const SCAN_Name&,
Algorithm_Factory&) const
{
- return 0;
+ return nullptr;
}
StreamCipher*
Engine::find_stream_cipher(const SCAN_Name&,
Algorithm_Factory&) const
{
- return 0;
+ return nullptr;
}
HashFunction*
Engine::find_hash(const SCAN_Name&,
Algorithm_Factory&) const
{
- return 0;
+ return nullptr;
}
MessageAuthenticationCode*
Engine::find_mac(const SCAN_Name&,
Algorithm_Factory&) const
{
- return 0;
+ return nullptr;
}
PBKDF*
Engine::find_pbkdf(const SCAN_Name&,
Algorithm_Factory&) const
{
- return 0;
+ return nullptr;
}
Modular_Exponentiator*
Engine::mod_exp(const BigInt&,
Power_Mod::Usage_Hints) const
{
- return 0;
+ return nullptr;
}
Keyed_Filter* Engine::get_cipher(const std::string&,
Cipher_Dir,
Algorithm_Factory&)
{
- return 0;
+ return nullptr;
}
PK_Ops::Key_Agreement*
Engine::get_key_agreement_op(const Private_Key&) const
{
- return 0;
+ return nullptr;
}
PK_Ops::Signature*
Engine::get_signature_op(const Private_Key&) const
{
- return 0;
+ return nullptr;
}
PK_Ops::Verification*
Engine::get_verify_op(const Public_Key&) const
{
- return 0;
+ return nullptr;
}
PK_Ops::Encryption*
Engine::get_encryption_op(const Public_Key&) const
{
- return 0;
+ return nullptr;
}
PK_Ops::Decryption*
Engine::get_decryption_op(const Private_Key&) const
{
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/gnump/gmp_wrap.h b/src/engine/gnump/gmp_wrap.h
index fc7aa856e..0a786f3ee 100644
--- a/src/engine/gnump/gmp_wrap.h
+++ b/src/engine/gnump/gmp_wrap.h
@@ -25,7 +25,7 @@ class GMP_MPZ
void encode(byte[], size_t) const;
size_t bytes() const;
- SecureVector<byte> to_bytes() const
+ secure_vector<byte> to_bytes() const
{ return BigInt::encode(to_bigint()); }
GMP_MPZ& operator=(const GMP_MPZ&);
diff --git a/src/engine/gnump/gnump_pk.cpp b/src/engine/gnump/gnump_pk.cpp
index 25735fe55..b2a2f9352 100644
--- a/src/engine/gnump/gnump_pk.cpp
+++ b/src/engine/gnump/gnump_pk.cpp
@@ -38,7 +38,7 @@ class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement
GMP_DH_KA_Operation(const DH_PrivateKey& dh) :
x(dh.get_x()), p(dh.group_p()) {}
- SecureVector<byte> agree(const byte w[], size_t w_len)
+ secure_vector<byte> agree(const byte w[], size_t w_len)
{
GMP_MPZ z(w, w_len);
mpz_powm(z.value, z.value, x.value, p.value);
@@ -66,14 +66,14 @@ class GMP_DSA_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const { return (q_bits + 7) / 8; }
size_t max_input_bits() const { return q_bits; }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const GMP_MPZ x, p, q, g;
size_t q_bits;
};
-SecureVector<byte>
+secure_vector<byte>
GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -104,7 +104,7 @@ GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
- SecureVector<byte> output(2*q_bytes);
+ secure_vector<byte> output(2*q_bytes);
r.encode(output, q_bytes);
s.encode(output + q_bytes, q_bytes);
return output;
@@ -192,7 +192,7 @@ class GMP_RSA_Private_Operation : public PK_Ops::Signature,
size_t max_input_bits() const { return (n_bits - 1); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
@@ -200,7 +200,7 @@ class GMP_RSA_Private_Operation : public PK_Ops::Signature,
return BigInt::encode_1363(x, (n_bits + 7) / 8);
}
- SecureVector<byte> decrypt(const byte msg[], size_t msg_len)
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
return BigInt::encode(private_op(m));
@@ -238,14 +238,14 @@ class GMP_RSA_Public_Operation : public PK_Ops::Verification,
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
- SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
return BigInt::encode_1363(public_op(m), n.bytes());
}
- SecureVector<byte> verify_mr(const byte msg[], size_t msg_len)
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
return BigInt::encode(public_op(m));
diff --git a/src/engine/openssl/bn_wrap.cpp b/src/engine/openssl/bn_wrap.cpp
index 779956824..0ac31f61b 100644
--- a/src/engine/openssl/bn_wrap.cpp
+++ b/src/engine/openssl/bn_wrap.cpp
@@ -15,7 +15,7 @@ namespace Botan {
OSSL_BN::OSSL_BN(const BigInt& in)
{
value = BN_new();
- SecureVector<byte> encoding = BigInt::encode(in);
+ secure_vector<byte> encoding = BigInt::encode(in);
if(in != 0)
BN_bin2bn(encoding, encoding.size(), value);
}
@@ -75,7 +75,7 @@ size_t OSSL_BN::bytes() const
*/
BigInt OSSL_BN::to_bigint() const
{
- SecureVector<byte> out(bytes());
+ secure_vector<byte> out(bytes());
BN_bn2bin(value, out);
return BigInt::decode(out);
}
diff --git a/src/engine/openssl/bn_wrap.h b/src/engine/openssl/bn_wrap.h
index c5c07a35c..177dbd8c7 100644
--- a/src/engine/openssl/bn_wrap.h
+++ b/src/engine/openssl/bn_wrap.h
@@ -25,7 +25,7 @@ class OSSL_BN
void encode(byte[], size_t) const;
size_t bytes() const;
- SecureVector<byte> to_bytes() const
+ secure_vector<byte> to_bytes() const
{ return BigInt::encode(to_bigint()); }
OSSL_BN& operator=(const OSSL_BN&);
diff --git a/src/engine/openssl/ossl_arc4.cpp b/src/engine/openssl/ossl_arc4.cpp
index 0b1f7f1f3..6469d263a 100644
--- a/src/engine/openssl/ossl_arc4.cpp
+++ b/src/engine/openssl/ossl_arc4.cpp
@@ -46,7 +46,7 @@ std::string ARC4_OpenSSL::name() const
{
if(SKIP == 0) return "ARC4";
if(SKIP == 256) return "MARK-4";
- else return "RC4_skip(" + to_string(SKIP) + ")";
+ else return "RC4_skip(" + std::to_string(SKIP) + ")";
}
/*
@@ -71,7 +71,7 @@ void ARC4_OpenSSL::cipher(const byte in[], byte out[], size_t length)
}
/**
-* Look for an OpenSSL-suported stream cipher (ARC4)
+* Look for an OpenSSL-supported stream cipher (ARC4)
*/
StreamCipher*
OpenSSL_Engine::find_stream_cipher(const SCAN_Name& request,
diff --git a/src/engine/openssl/ossl_bc.cpp b/src/engine/openssl/ossl_bc.cpp
index 36f78205f..d419f56be 100644
--- a/src/engine/openssl/ossl_bc.cpp
+++ b/src/engine/openssl/ossl_bc.cpp
@@ -123,7 +123,7 @@ void EVP_BlockCipher::decrypt_n(const byte in[], byte out[],
*/
void EVP_BlockCipher::key_schedule(const byte key[], size_t length)
{
- SecureVector<byte> full_key(key, length);
+ secure_vector<byte> full_key(key, length);
if(cipher_name == "TripleDES" && length == 16)
{
diff --git a/src/engine/openssl/ossl_pk.cpp b/src/engine/openssl/ossl_pk.cpp
index 23ae6b25d..2557ec297 100644
--- a/src/engine/openssl/ossl_pk.cpp
+++ b/src/engine/openssl/ossl_pk.cpp
@@ -36,7 +36,7 @@ class OSSL_DH_KA_Operation : public PK_Ops::Key_Agreement
OSSL_DH_KA_Operation(const DH_PrivateKey& dh) :
x(dh.get_x()), p(dh.group_p()) {}
- SecureVector<byte> agree(const byte w[], size_t w_len)
+ secure_vector<byte> agree(const byte w[], size_t w_len)
{
OSSL_BN i(w, w_len), r;
BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value);
@@ -65,7 +65,7 @@ class OSSL_DSA_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const { return (q_bits + 7) / 8; }
size_t max_input_bits() const { return q_bits; }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const OSSL_BN x, p, q, g;
@@ -73,7 +73,7 @@ class OSSL_DSA_Signature_Operation : public PK_Ops::Signature
size_t q_bits;
};
-SecureVector<byte>
+secure_vector<byte>
OSSL_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -103,7 +103,7 @@ OSSL_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
if(BN_is_zero(r.value) || BN_is_zero(s.value))
throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero");
- SecureVector<byte> output(2*q_bytes);
+ secure_vector<byte> output(2*q_bytes);
r.encode(output, q_bytes);
s.encode(output + q_bytes, q_bytes);
return output;
@@ -191,7 +191,7 @@ class OSSL_RSA_Private_Operation : public PK_Ops::Signature,
size_t max_input_bits() const { return (n_bits - 1); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
@@ -199,7 +199,7 @@ class OSSL_RSA_Private_Operation : public PK_Ops::Signature,
return BigInt::encode_1363(x, (n_bits + 7) / 8);
}
- SecureVector<byte> decrypt(const byte msg[], size_t msg_len)
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
return BigInt::encode(private_op(m));
@@ -237,14 +237,14 @@ class OSSL_RSA_Public_Operation : public PK_Ops::Verification,
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
- SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
return BigInt::encode_1363(public_op(m), n.bytes());
}
- SecureVector<byte> verify_mr(const byte msg[], size_t msg_len)
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
return BigInt::encode(public_op(m));
diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp
index f9a731a82..70529f1fd 100644
--- a/src/engine/simd_engine/simd_engine.cpp
+++ b/src/engine/simd_engine/simd_engine.cpp
@@ -68,7 +68,7 @@ SIMD_Engine::find_block_cipher(const SCAN_Name& request,
return new XTEA_SIMD;
#endif
- return 0;
+ return nullptr;
}
HashFunction*
@@ -80,7 +80,7 @@ SIMD_Engine::find_hash(const SCAN_Name& request,
return new SHA_160_SSE2;
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/engine/simd_engine/simd_engine.h b/src/engine/simd_engine/simd_engine.h
index 73f7d2233..66c8886f1 100644
--- a/src/engine/simd_engine/simd_engine.h
+++ b/src/engine/simd_engine/simd_engine.h
@@ -23,7 +23,7 @@ class SIMD_Engine : public Engine
BlockCipher* find_block_cipher(const SCAN_Name&,
Algorithm_Factory&) const;
- HashFunction* find_hash(const SCAN_Name& reqeust,
+ HashFunction* find_hash(const SCAN_Name& request,
Algorithm_Factory&) const;
};
diff --git a/src/entropy/cryptoapi_rng/es_capi.cpp b/src/entropy/cryptoapi_rng/es_capi.cpp
index c9069ce65..a706b4d5c 100644
--- a/src/entropy/cryptoapi_rng/es_capi.cpp
+++ b/src/entropy/cryptoapi_rng/es_capi.cpp
@@ -55,7 +55,7 @@ class CSP_Handle
*/
void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum)
{
- MemoryRegion<byte>& io_buffer = accum.get_io_buffer(32);
+ secure_vector<byte>& io_buffer = accum.get_io_buffer(32);
for(size_t i = 0; i != prov_types.size(); ++i)
{
diff --git a/src/entropy/dev_random/dev_random.cpp b/src/entropy/dev_random/dev_random.cpp
index 9e4f0b373..3090f9510 100644
--- a/src/entropy/dev_random/dev_random.cpp
+++ b/src/entropy/dev_random/dev_random.cpp
@@ -45,7 +45,7 @@ size_t Device_EntropySource::Device_Reader::get(byte out[], size_t length,
timeout.tv_sec = (ms_wait_time / 1000);
timeout.tv_usec = (ms_wait_time % 1000) * 1000;
- if(::select(fd + 1, &read_set, 0, 0, &timeout) < 0)
+ if(::select(fd + 1, &read_set, nullptr, nullptr, &timeout) < 0)
return 0;
if(!(FD_ISSET(fd, &read_set)))
@@ -111,7 +111,7 @@ void Device_EntropySource::poll(Entropy_Accumulator& accum)
accum.desired_remaining_bits() / ENTROPY_BITS_PER_BYTE, 32);
const size_t read_wait_ms = std::max<size_t>(go_get, 100);
- MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
+ secure_vector<byte>& io_buffer = accum.get_io_buffer(go_get);
for(size_t i = 0; i != devices.size(); ++i)
{
diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp
index e0ebf9509..d8dbecd44 100644
--- a/src/entropy/egd/es_egd.cpp
+++ b/src/entropy/egd/es_egd.cpp
@@ -139,7 +139,7 @@ void EGD_EntropySource::poll(Entropy_Accumulator& accum)
{
size_t go_get = std::min<size_t>(accum.desired_remaining_bits() / 8, 32);
- MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
+ secure_vector<byte>& io_buffer = accum.get_io_buffer(go_get);
for(size_t i = 0; i != sockets.size(); ++i)
{
diff --git a/src/entropy/entropy_src.h b/src/entropy/entropy_src.h
index 3f15b5907..e130574f4 100644
--- a/src/entropy/entropy_src.h
+++ b/src/entropy/entropy_src.h
@@ -35,7 +35,7 @@ class BOTAN_DLL Entropy_Accumulator
* @param size requested size for the I/O buffer
* @return cached I/O buffer for repeated polls
*/
- MemoryRegion<byte>& get_io_buffer(size_t size)
+ secure_vector<byte>& get_io_buffer(size_t size)
{ io_buffer.resize(size); return io_buffer; }
/**
@@ -87,7 +87,7 @@ class BOTAN_DLL Entropy_Accumulator
private:
virtual void add_bytes(const byte bytes[], size_t length) = 0;
- SecureVector<byte> io_buffer;
+ secure_vector<byte> io_buffer;
size_t entropy_goal;
double collected_bits;
};
diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp
index dd1fc6f7c..c6b31d996 100644
--- a/src/entropy/hres_timer/hres_timer.cpp
+++ b/src/entropy/hres_timer/hres_timer.cpp
@@ -7,9 +7,8 @@
#include <botan/internal/hres_timer.h>
#include <botan/cpuid.h>
-#include <botan/time.h>
-#if defined(BOTAN_TARGET_OS_IS_WINDOWS)
+#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER)
#include <windows.h>
#endif
@@ -20,8 +19,7 @@ namespace Botan {
*/
void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
{
- // If Windows, grab the Performance Counter (usually TSC or PIT)
-#if defined(BOTAN_TARGET_OS_IS_WINDOWS)
+#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER)
{
LARGE_INTEGER tv;
::QueryPerformanceCounter(&tv);
diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp
index 8b4408aee..7d72e7752 100644
--- a/src/entropy/proc_walk/es_ftw.cpp
+++ b/src/entropy/proc_walk/es_ftw.cpp
@@ -42,7 +42,7 @@ class Directory_Walker : public File_Descriptor_Source
{
public:
Directory_Walker(const std::string& root) :
- m_cur_dir(std::make_pair<DIR*, std::string>(0, ""))
+ m_cur_dir(std::make_pair<DIR*, std::string>(nullptr, ""))
{
if(DIR* root_dir = ::opendir(root.c_str()))
m_cur_dir = std::make_pair(root_dir, root);
@@ -71,15 +71,13 @@ std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent()
{
while(m_cur_dir.first)
{
- struct dirent* dir = ::readdir(m_cur_dir.first);
-
- if(dir)
- return std::make_pair<struct dirent*, std::string>(dir, m_cur_dir.second);
+ if(struct dirent* dir = ::readdir(m_cur_dir.first))
+ return std::make_pair(dir, m_cur_dir.second);
::closedir(m_cur_dir.first);
- m_cur_dir = std::make_pair<DIR*, std::string>(0, "");
+ m_cur_dir = std::make_pair<DIR*, std::string>(nullptr, "");
- while(!m_dirlist.empty() && m_cur_dir.first == 0)
+ while(!m_dirlist.empty() && !m_cur_dir.first)
{
const std::string next_dir_name = m_dirlist[0];
m_dirlist.pop_front();
@@ -89,7 +87,7 @@ std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent()
}
}
- return std::make_pair<struct dirent*, std::string>(0, ""); // nothing left
+ return std::make_pair<struct dirent*, std::string>(nullptr, ""); // nothing left
}
int Directory_Walker::next_fd()
@@ -133,9 +131,8 @@ int Directory_Walker::next_fd()
/**
* FTW_EntropySource Constructor
*/
-FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
+FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p), dir(nullptr)
{
- dir = 0;
}
/**
@@ -144,6 +141,7 @@ FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
FTW_EntropySource::~FTW_EntropySource()
{
delete dir;
+ dir = nullptr;
}
void FTW_EntropySource::poll(Entropy_Accumulator& accum)
@@ -153,7 +151,7 @@ void FTW_EntropySource::poll(Entropy_Accumulator& accum)
if(!dir)
dir = new Directory_Walker(path);
- MemoryRegion<byte>& io_buffer = accum.get_io_buffer(4096);
+ secure_vector<byte>& io_buffer = accum.get_io_buffer(4096);
for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i)
{
@@ -163,7 +161,7 @@ void FTW_EntropySource::poll(Entropy_Accumulator& accum)
if(fd == -1)
{
delete dir;
- dir = 0;
+ dir = nullptr;
break;
}
diff --git a/src/entropy/rdrand/info.txt b/src/entropy/rdrand/info.txt
new file mode 100644
index 000000000..4b9362d61
--- /dev/null
+++ b/src/entropy/rdrand/info.txt
@@ -0,0 +1,20 @@
+define ENTROPY_SRC_RDRAND
+
+<source>
+rdrand.cpp
+</source>
+
+<header:internal>
+rdrand.h
+</header:internal>
+
+<arch>
+x86
+x86_64
+</arch>
+
+<cc>
+gcc
+clang
+icc
+</cc>
diff --git a/src/entropy/rdrand/rdrand.cpp b/src/entropy/rdrand/rdrand.cpp
new file mode 100644
index 000000000..51b2bd5f6
--- /dev/null
+++ b/src/entropy/rdrand/rdrand.cpp
@@ -0,0 +1,60 @@
+/*
+* Entropy Source Using Intel's rdrand instruction
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/rdrand.h>
+#include <botan/cpuid.h>
+
+#if !defined(BOTAN_USE_GCC_INLINE_ASM)
+ #include <immintrin.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get the timestamp
+*/
+void Intel_Rdrand::poll(Entropy_Accumulator& accum)
+ {
+ if(!CPUID::has_rdrand())
+ return;
+
+ /*
+ * Put an upper bound on the total entropy we're willing to claim
+ * for any one polling of rdrand to prevent it from swamping our
+ * poll. Internally, the rdrand system is a DRGB that reseeds at a
+ * somewhat unpredictable rate (the current conditions are
+ * documented, but that might not be true for different
+ * implementations, eg on Haswell or a future AMD chip, so I don't
+ * want to assume). This limit ensures we're going to poll at least
+ * one other source so we have some diversity in our inputs.
+ */
+
+ const size_t POLL_UPPER_BOUND = 96;
+ const size_t RDRAND_POLLS = 32;
+ const double ENTROPY_PER_POLL =
+ static_cast<double>(POLL_UPPER_BOUND) / (RDRAND_POLLS * 4);
+
+ for(size_t i = 0; i != RDRAND_POLLS; ++i)
+ {
+ unsigned int r;
+
+#if BOTAN_USE_GCC_INLINE_ASM
+ int cf = 0;
+
+ // Encoding of rdrand %eax
+ asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" :
+ "=a" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
+#else
+ int cf = _rdrand32_step(&r);
+#endif
+
+ if(cf == 1)
+ accum.add(r, ENTROPY_PER_POLL);
+ }
+ }
+
+}
diff --git a/src/entropy/rdrand/rdrand.h b/src/entropy/rdrand/rdrand.h
new file mode 100644
index 000000000..d7629d37f
--- /dev/null
+++ b/src/entropy/rdrand/rdrand.h
@@ -0,0 +1,28 @@
+/*
+* Entropy Source Using Intel's rdrand instruction
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_RDRAND_H__
+#define BOTAN_ENTROPY_SRC_RDRAND_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Entropy source using the rdrand instruction first introduced on
+* Intel's Ivy Bridge architecture.
+*/
+class Intel_Rdrand : public EntropySource
+ {
+ public:
+ std::string name() const { return "Intel Rdrand"; }
+ void poll(Entropy_Accumulator& accum);
+ };
+
+}
+
+#endif
diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp
index b989e0213..f72a691d2 100644
--- a/src/entropy/unix_procs/es_unix.cpp
+++ b/src/entropy/unix_procs/es_unix.cpp
@@ -68,7 +68,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum)
"/etc/passwd",
".",
"..",
- 0 };
+ nullptr };
for(size_t i = 0; stat_targets[i]; i++)
{
@@ -93,7 +93,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum)
const size_t MINIMAL_WORKING = 16;
- MemoryRegion<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE);
for(size_t i = 0; i != sources.size(); i++)
{
diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp
index 930444075..823da2717 100644
--- a/src/entropy/unix_procs/unix_cmd.cpp
+++ b/src/entropy/unix_procs/unix_cmd.cpp
@@ -29,10 +29,10 @@ void do_exec(const std::vector<std::string>& arg_list,
{
const size_t args = arg_list.size() - 1;
- const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0;
- const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0;
- const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0;
- const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0;
+ const char* arg1 = (args >= 1) ? arg_list[1].c_str() : nullptr;
+ const char* arg2 = (args >= 2) ? arg_list[2].c_str() : nullptr;
+ const char* arg3 = (args >= 3) ? arg_list[3].c_str() : nullptr;
+ const char* arg4 = (args >= 4) ? arg_list[4].c_str() : nullptr;
for(size_t j = 0; j != paths.size(); j++)
{
@@ -74,7 +74,7 @@ size_t DataSource_Command::read(byte buf[], size_t length)
tv.tv_usec = MAX_BLOCK_USECS;
ssize_t got = 0;
- if(::select(pipe->fd + 1, &set, 0, 0, &tv) == 1)
+ if(::select(pipe->fd + 1, &set, nullptr, nullptr, &tv) == 1)
{
if(FD_ISSET(pipe->fd, &set))
got = ::read(pipe->fd, buf, length);
@@ -182,7 +182,7 @@ void DataSource_Command::shutdown_pipe()
{
if(pipe)
{
- pid_t reaped = waitpid(pipe->pid, 0, WNOHANG);
+ pid_t reaped = waitpid(pipe->pid, nullptr, WNOHANG);
if(reaped == 0)
{
@@ -191,21 +191,21 @@ void DataSource_Command::shutdown_pipe()
struct ::timeval tv;
tv.tv_sec = 0;
tv.tv_usec = KILL_WAIT;
- select(0, 0, 0, 0, &tv);
+ select(0, nullptr, nullptr, nullptr, &tv);
- reaped = ::waitpid(pipe->pid, 0, WNOHANG);
+ reaped = ::waitpid(pipe->pid, nullptr, WNOHANG);
if(reaped == 0)
{
::kill(pipe->pid, SIGKILL);
do
- reaped = ::waitpid(pipe->pid, 0, 0);
+ reaped = ::waitpid(pipe->pid, nullptr, 0);
while(reaped == -1);
}
}
delete pipe;
- pipe = 0;
+ pipe = nullptr;
}
}
@@ -223,7 +223,7 @@ DataSource_Command::DataSource_Command(const std::string& prog_and_args,
if(arg_list.size() > 5)
throw Invalid_Argument("DataSource_Command: Too many args");
- pipe = 0;
+ pipe = nullptr;
create_pipe(paths);
}
diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp
index 337733b5f..dbc46c7e6 100644
--- a/src/filters/algo_filt.cpp
+++ b/src/filters/algo_filt.cpp
@@ -92,7 +92,7 @@ Hash_Filter::Hash_Filter(const std::string& algo_spec,
*/
void Hash_Filter::end_msg()
{
- SecureVector<byte> output = hash->final();
+ secure_vector<byte> output = hash->final();
if(OUTPUT_LENGTH)
send(output, std::min<size_t>(OUTPUT_LENGTH, output.size()));
else
@@ -125,7 +125,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key,
*/
void MAC_Filter::end_msg()
{
- SecureVector<byte> output = mac->final();
+ secure_vector<byte> output = mac->final();
if(OUTPUT_LENGTH)
send(output, std::min<size_t>(OUTPUT_LENGTH, output.size()));
else
diff --git a/src/filters/basefilt.h b/src/filters/basefilt.h
index adde3dd54..5252be973 100644
--- a/src/filters/basefilt.h
+++ b/src/filters/basefilt.h
@@ -39,7 +39,8 @@ class BOTAN_DLL Chain : public Fanout_Filter
* Construct a chain of up to four filters. The filters are set
* up in the same order as the arguments.
*/
- Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+ Chain(Filter* = nullptr, Filter* = nullptr,
+ Filter* = nullptr, Filter* = nullptr);
/**
* Construct a chain from range of filters
@@ -65,7 +66,7 @@ class BOTAN_DLL Fork : public Fanout_Filter
/**
* Construct a Fork filter with up to four forks.
*/
- Fork(Filter*, Filter*, Filter* = 0, Filter* = 0);
+ Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr);
/**
* Construct a Fork from range of filters
diff --git a/src/filters/buf_filt.h b/src/filters/buf_filt.h
index 87180e3e1..9a3fc9a2b 100644
--- a/src/filters/buf_filt.h
+++ b/src/filters/buf_filt.h
@@ -27,6 +27,12 @@ class BOTAN_DLL Buffered_Filter
*/
void write(const byte in[], size_t length);
+ template<typename Alloc>
+ void write(const std::vector<byte, Alloc>& in, size_t length)
+ {
+ write(&in[0], length);
+ }
+
/**
* Finish a message, emitting to buffered_block and buffered_final
* Will throw an exception if less than final_minimum bytes were
@@ -78,7 +84,7 @@ class BOTAN_DLL Buffered_Filter
private:
size_t main_block_mod, final_minimum;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
size_t buffer_pos;
};
diff --git a/src/filters/bzip2/bzip2.cpp b/src/filters/bzip2/bzip2.cpp
index a291c1173..18a53558c 100644
--- a/src/filters/bzip2/bzip2.cpp
+++ b/src/filters/bzip2/bzip2.cpp
@@ -48,7 +48,7 @@ void* bzip_malloc(void* info_ptr, int n, int size)
void bzip_free(void* info_ptr, void* ptr)
{
Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
- std::map<void*, size_t>::const_iterator i = info->current_allocs.find(ptr);
+ auto i = info->current_allocs.find(ptr);
if(i == info->current_allocs.end())
throw Invalid_Argument("bzip_free: Got pointer not allocated by us");
info->alloc->deallocate(ptr, i->second);
diff --git a/src/filters/bzip2/bzip2.h b/src/filters/bzip2/bzip2.h
index b3b222eb2..2505cf54e 100644
--- a/src/filters/bzip2/bzip2.h
+++ b/src/filters/bzip2/bzip2.h
@@ -33,7 +33,7 @@ class BOTAN_DLL Bzip_Compression : public Filter
void clear();
const size_t level;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
class Bzip_Stream* bz;
};
@@ -55,7 +55,7 @@ class BOTAN_DLL Bzip_Decompression : public Filter
void clear();
const bool small_mem;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
class Bzip_Stream* bz;
bool no_writes;
};
diff --git a/src/filters/codec_filt/b64_filt.cpp b/src/filters/codec_filt/b64_filt.cpp
index 9341571d4..b804b33c7 100644
--- a/src/filters/codec_filt/b64_filt.cpp
+++ b/src/filters/codec_filt/b64_filt.cpp
@@ -79,7 +79,7 @@ void Base64_Encoder::do_output(const byte input[], size_t length)
*/
void Base64_Encoder::write(const byte input[], size_t length)
{
- in.copy(position, input, length);
+ buffer_insert(in, position, input, length);
if(position + length >= in.size())
{
encode_and_send(&in[0], in.size());
@@ -91,7 +91,7 @@ void Base64_Encoder::write(const byte input[], size_t length)
input += in.size();
length -= in.size();
}
- in.copy(input, length);
+ copy_mem(&in[0], input, length);
position = 0;
}
position += length;
diff --git a/src/filters/codec_filt/b64_filt.h b/src/filters/codec_filt/b64_filt.h
index afff53f30..dcb3cdbd5 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;
- MemoryVector<byte> in, out;
+ std::vector<byte> in, out;
size_t position, out_position;
};
@@ -79,7 +79,7 @@ class BOTAN_DLL Base64_Decoder : public Filter
Base64_Decoder(Decoder_Checking checking = NONE);
private:
const Decoder_Checking checking;
- MemoryVector<byte> in, out;
+ std::vector<byte> in, out;
size_t position;
};
diff --git a/src/filters/codec_filt/hex_filt.cpp b/src/filters/codec_filt/hex_filt.cpp
index 3d56beec4..e85bdb17e 100644
--- a/src/filters/codec_filt/hex_filt.cpp
+++ b/src/filters/codec_filt/hex_filt.cpp
@@ -75,7 +75,7 @@ void Hex_Encoder::encode_and_send(const byte block[], size_t length)
*/
void Hex_Encoder::write(const byte input[], size_t length)
{
- in.copy(position, input, length);
+ buffer_insert(in, position, input, length);
if(position + length >= in.size())
{
encode_and_send(&in[0], in.size());
@@ -87,7 +87,7 @@ void Hex_Encoder::write(const byte input[], size_t length)
input += in.size();
length -= in.size();
}
- in.copy(input, length);
+ copy_mem(&in[0], input, length);
position = 0;
}
position += length;
diff --git a/src/filters/codec_filt/hex_filt.h b/src/filters/codec_filt/hex_filt.h
index 0dc38c804..dbe6b9bae 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;
- MemoryVector<byte> in, out;
+ std::vector<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;
- MemoryVector<byte> in, out;
+ std::vector<byte> in, out;
size_t position;
};
diff --git a/src/filters/data_snk.cpp b/src/filters/data_snk.cpp
index d651dcba7..2903e5e1f 100644
--- a/src/filters/data_snk.cpp
+++ b/src/filters/data_snk.cpp
@@ -29,7 +29,7 @@ void DataSink_Stream::write(const byte out[], size_t length)
DataSink_Stream::DataSink_Stream(std::ostream& out,
const std::string& name) :
identifier(name),
- sink_p(0),
+ sink_p(nullptr),
sink(out)
{
}
diff --git a/src/filters/data_snk.h b/src/filters/data_snk.h
index e31cb9d28..6b9da0b4d 100644
--- a/src/filters/data_snk.h
+++ b/src/filters/data_snk.h
@@ -22,9 +22,9 @@ class BOTAN_DLL DataSink : public Filter
bool attachable() { return false; }
DataSink() {}
virtual ~DataSink() {}
- private:
- DataSink& operator=(const DataSink&) { return (*this); }
- DataSink(const DataSink&);
+
+ DataSink& operator=(const DataSink&) = delete;
+ DataSink(const DataSink&) = delete;
};
/**
diff --git a/src/filters/data_src.cpp b/src/filters/data_src.cpp
index da67baa98..cc100ab13 100644
--- a/src/filters/data_src.cpp
+++ b/src/filters/data_src.cpp
@@ -77,26 +77,10 @@ bool DataSource_Memory::end_of_data() const
/*
* DataSource_Memory Constructor
*/
-DataSource_Memory::DataSource_Memory(const byte in[], size_t length) :
- source(in, length)
- {
- offset = 0;
- }
-
-/*
-* DataSource_Memory Constructor
-*/
-DataSource_Memory::DataSource_Memory(const MemoryRegion<byte>& in) :
- source(in)
- {
- offset = 0;
- }
-
-/*
-* DataSource_Memory Constructor
-*/
DataSource_Memory::DataSource_Memory(const std::string& in) :
- source(reinterpret_cast<const byte*>(in.data()), in.length())
+ source(reinterpret_cast<const byte*>(in.data()),
+ reinterpret_cast<const byte*>(in.data()) + in.length()),
+ offset(0)
{
offset = 0;
}
@@ -127,7 +111,7 @@ size_t DataSource_Stream::peek(byte out[], size_t length, size_t offset) const
if(offset)
{
- SecureVector<byte> buf(offset);
+ secure_vector<byte> buf(offset);
source.read(reinterpret_cast<char*>(&buf[0]), buf.size());
if(source.bad())
throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
@@ -190,7 +174,7 @@ DataSource_Stream::DataSource_Stream(const std::string& path,
DataSource_Stream::DataSource_Stream(std::istream& in,
const std::string& name) :
identifier(name),
- source_p(0),
+ source_p(nullptr),
source(in),
total_read(0)
{
diff --git a/src/filters/data_src.h b/src/filters/data_src.h
index a274de8e2..62bdacd33 100644
--- a/src/filters/data_src.h
+++ b/src/filters/data_src.h
@@ -81,9 +81,8 @@ class BOTAN_DLL DataSource
DataSource() {}
virtual ~DataSource() {}
- private:
- DataSource& operator=(const DataSource&) { return (*this); }
- DataSource(const DataSource&);
+ DataSource& operator=(const DataSource&) = delete;
+ DataSource(const DataSource&) = delete;
};
/**
@@ -107,15 +106,24 @@ class BOTAN_DLL DataSource_Memory : public DataSource
* @param in the byte array to read from
* @param length the length of the byte array
*/
- DataSource_Memory(const byte in[], size_t length);
+ DataSource_Memory(const byte in[], size_t length) :
+ source(in, in + length), offset(0) {}
+
+ /**
+ * Construct a memory source that reads from a secure_vector
+ * @param in the MemoryRegion to read from
+ */
+ DataSource_Memory(const secure_vector<byte>& in) :
+ source(in), offset(0) {}
/**
- * Construct a memory source that reads from a MemoryRegion
+ * Construct a memory source that reads from a std::vector
* @param in the MemoryRegion to read from
*/
- DataSource_Memory(const MemoryRegion<byte>& in);
+ DataSource_Memory(const std::vector<byte>& in) :
+ source(&in[0], &in[in.size()]), offset(0) {}
private:
- SecureVector<byte> source;
+ secure_vector<byte> source;
size_t offset;
};
diff --git a/src/filters/fd_unix/fd_unix.cpp b/src/filters/fd_unix/fd_unix.cpp
index 3a9253b5e..dc6fbe696 100644
--- a/src/filters/fd_unix/fd_unix.cpp
+++ b/src/filters/fd_unix/fd_unix.cpp
@@ -16,7 +16,7 @@ namespace Botan {
*/
int operator<<(int fd, Pipe& pipe)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(pipe.remaining())
{
size_t got = pipe.read(&buffer[0], buffer.size());
@@ -38,7 +38,7 @@ int operator<<(int fd, Pipe& pipe)
*/
int operator>>(int fd, Pipe& pipe)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(true)
{
ssize_t ret = read(fd, &buffer[0], buffer.size());
diff --git a/src/filters/filter.cpp b/src/filters/filter.cpp
index c33f25814..9432f0304 100644
--- a/src/filters/filter.cpp
+++ b/src/filters/filter.cpp
@@ -96,7 +96,7 @@ Filter* Filter::get_next() const
{
if(port_num < next.size())
return next[port_num];
- return 0;
+ return nullptr;
}
/*
@@ -104,7 +104,7 @@ Filter* Filter::get_next() const
*/
void Filter::set_next(Filter* filters[], size_t size)
{
- while(size && filters && filters[size-1] == 0)
+ while(size && filters && filters[size-1] == nullptr)
--size;
next.clear();
diff --git a/src/filters/filter.h b/src/filters/filter.h
index 962b2816e..581d95c58 100644
--- a/src/filters/filter.h
+++ b/src/filters/filter.h
@@ -10,6 +10,7 @@
#include <botan/secmem.h>
#include <vector>
+#include <string>
namespace Botan {
@@ -65,22 +66,33 @@ class BOTAN_DLL Filter
/**
* @param in some input for the filter
*/
- void send(const MemoryRegion<byte>& in) { send(&in[0], in.size()); }
+ void send(const secure_vector<byte>& in) { send(&in[0], in.size()); }
+
+ /**
+ * @param in some input for the filter
+ */
+ void send(const std::vector<byte>& in) { send(&in[0], in.size()); }
+
+ /**
+ * @param in some input for the filter
+ * @param length the number of bytes of in to send
+ */
+ void send(const secure_vector<byte>& in, size_t length)
+ {
+ send(&in[0], length);
+ }
/**
* @param in some input for the filter
* @param length the number of bytes of in to send
*/
- void send(const MemoryRegion<byte>& in, size_t length)
+ void send(const std::vector<byte>& in, size_t length)
{
send(&in[0], length);
}
Filter();
private:
- Filter(const Filter&) {}
- Filter& operator=(const Filter&) { return (*this); }
-
/**
* Start a new message in *this and all following filters. Only for
* internal use, not intended for use in client applications.
@@ -96,6 +108,9 @@ class BOTAN_DLL Filter
friend class Pipe;
friend class Fanout_Filter;
+ Filter(const Filter&) = delete;
+ Filter& operator=(const Filter&) = delete;
+
size_t total_ports() const;
size_t current_port() const { return port_num; }
@@ -120,7 +135,7 @@ class BOTAN_DLL Filter
void set_next(Filter* filters[], size_t count);
Filter* get_next() const;
- SecureVector<byte> write_queue;
+ secure_vector<byte> write_queue;
std::vector<Filter*> next;
size_t port_num, filter_owns;
diff --git a/src/filters/filters.h b/src/filters/filters.h
index b409e78f5..08b505bc0 100644
--- a/src/filters/filters.h
+++ b/src/filters/filters.h
@@ -94,7 +94,7 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
~StreamCipher_Filter() { delete cipher; }
private:
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
StreamCipher* cipher;
};
diff --git a/src/filters/modes/cbc/cbc.cpp b/src/filters/modes/cbc/cbc.cpp
index b464d075f..00518fc86 100644
--- a/src/filters/modes/cbc/cbc.cpp
+++ b/src/filters/modes/cbc/cbc.cpp
@@ -65,9 +65,9 @@ void CBC_Encryption::buffered_block(const byte input[], size_t length)
for(size_t i = 0; i != blocks; ++i)
{
- xor_buf(state, input + i * cipher->block_size(), state.size());
+ xor_buf(&state[0], input + i * cipher->block_size(), state.size());
cipher->encrypt(state);
- send(state, state.size());
+ send(state);
}
}
@@ -91,13 +91,13 @@ void CBC_Encryption::end_msg()
{
size_t last_block = current_position() % cipher->block_size();
- SecureVector<byte> padding(cipher->block_size());
- padder->pad(padding, padding.size(), last_block);
+ std::vector<byte> padding(cipher->block_size());
+ padder->pad(&padding[0], padding.size(), last_block);
size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block);
if(pad_bytes)
- Buffered_Filter::write(padding, pad_bytes);
+ Buffered_Filter::write(&padding[0], pad_bytes);
Buffered_Filter::end_msg();
}
@@ -170,7 +170,7 @@ void CBC_Decryption::buffered_block(const byte input[], size_t length)
cipher->decrypt_n(input, &temp[0], to_proc);
- xor_buf(temp, state, cipher->block_size());
+ xor_buf(&temp[0], &state[0], cipher->block_size());
for(size_t i = 1; i < to_proc; ++i)
xor_buf(&temp[i * cipher->block_size()],
@@ -202,9 +202,9 @@ void CBC_Decryption::buffered_final(const byte input[], size_t length)
input += extra_blocks * cipher->block_size();
- cipher->decrypt(input, temp);
- xor_buf(temp, state, cipher->block_size());
- send(temp, padder->unpad(temp, cipher->block_size()));
+ cipher->decrypt(&input[0], &temp[0]);
+ xor_buf(&temp[0], &state[0], cipher->block_size());
+ send(&temp[0], padder->unpad(&temp[0], cipher->block_size()));
copy_mem(&state[0], input, state.size()); // save for IV chaining
}
diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h
index d828f53a6..4fd0f7d66 100644
--- a/src/filters/modes/cbc/cbc.h
+++ b/src/filters/modes/cbc/cbc.h
@@ -52,7 +52,7 @@ class BOTAN_DLL CBC_Encryption : public Keyed_Filter,
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- SecureVector<byte> state;
+ secure_vector<byte> state;
};
/**
@@ -92,7 +92,7 @@ class BOTAN_DLL CBC_Decryption : public Keyed_Filter,
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- SecureVector<byte> state, temp;
+ secure_vector<byte> state, temp;
};
}
diff --git a/src/filters/modes/cfb/cfb.cpp b/src/filters/modes/cfb/cfb.cpp
index 8f7471c98..2b7cca84a 100644
--- a/src/filters/modes/cfb/cfb.cpp
+++ b/src/filters/modes/cfb/cfb.cpp
@@ -26,7 +26,7 @@ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, size_t fback_bits)
if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size())
throw Invalid_Argument("CFB_Encryption: Invalid feedback size " +
- to_string(fback_bits));
+ std::to_string(fback_bits));
}
/*
@@ -46,7 +46,7 @@ CFB_Encryption::CFB_Encryption(BlockCipher* ciph,
if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size())
throw Invalid_Argument("CFB_Encryption: Invalid feedback size " +
- to_string(fback_bits));
+ std::to_string(fback_bits));
set_key(key);
set_iv(iv);
@@ -61,7 +61,7 @@ void CFB_Encryption::set_iv(const InitializationVector& iv)
zeroise(buffer);
position = 0;
- cipher->encrypt(state, buffer);
+ cipher->encrypt(&state[0], &buffer[0]);
}
/*
@@ -82,7 +82,10 @@ void CFB_Encryption::write(const byte input[], size_t length)
{
for(size_t j = 0; j != cipher->block_size() - feedback; ++j)
state[j] = state[j + feedback];
- state.copy(cipher->block_size() - feedback, buffer, feedback);
+
+ buffer_insert(state, cipher->block_size() - feedback,
+ &buffer[0], feedback);
+
cipher->encrypt(state, buffer);
position = 0;
}
@@ -103,7 +106,7 @@ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, size_t fback_bits)
if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size())
throw Invalid_Argument("CFB_Decryption: Invalid feedback size " +
- to_string(fback_bits));
+ std::to_string(fback_bits));
}
/*
@@ -123,7 +126,7 @@ CFB_Decryption::CFB_Decryption(BlockCipher* ciph,
if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size())
throw Invalid_Argument("CFB_Decryption: Invalid feedback size " +
- to_string(fback_bits));
+ std::to_string(fback_bits));
set_key(key);
set_iv(iv);
@@ -151,7 +154,7 @@ void CFB_Decryption::write(const byte input[], size_t length)
size_t xored = std::min(feedback - position, length);
xor_buf(&buffer[position], input, xored);
send(&buffer[position], xored);
- buffer.copy(position, input, xored);
+ buffer_insert(buffer, position, input, xored);
input += xored;
length -= xored;
position += xored;
@@ -159,7 +162,10 @@ void CFB_Decryption::write(const byte input[], size_t length)
{
for(size_t j = 0; j != cipher->block_size() - feedback; ++j)
state[j] = state[j + feedback];
- state.copy(cipher->block_size() - feedback, buffer, feedback);
+
+ buffer_insert(state, cipher->block_size() - feedback,
+ &buffer[0], feedback);
+
cipher->encrypt(state, buffer);
position = 0;
}
diff --git a/src/filters/modes/cfb/cfb.h b/src/filters/modes/cfb/cfb.h
index 64eb1e832..212ac76da 100644
--- a/src/filters/modes/cfb/cfb.h
+++ b/src/filters/modes/cfb/cfb.h
@@ -43,7 +43,7 @@ class BOTAN_DLL CFB_Encryption : public Keyed_Filter
void write(const byte[], size_t);
BlockCipher* cipher;
- SecureVector<byte> buffer, state;
+ secure_vector<byte> buffer, state;
size_t position, feedback;
};
@@ -77,7 +77,7 @@ class BOTAN_DLL CFB_Decryption : public Keyed_Filter
void write(const byte[], size_t);
BlockCipher* cipher;
- SecureVector<byte> buffer, state;
+ secure_vector<byte> buffer, state;
size_t position, feedback;
};
diff --git a/src/filters/modes/cts/cts.cpp b/src/filters/modes/cts/cts.cpp
index c654c8719..f77a28dd5 100644
--- a/src/filters/modes/cts/cts.cpp
+++ b/src/filters/modes/cts/cts.cpp
@@ -56,7 +56,7 @@ void CTS_Encryption::set_iv(const InitializationVector& iv)
*/
void CTS_Encryption::encrypt(const byte block[])
{
- xor_buf(state, block, cipher->block_size());
+ xor_buf(&state[0], &block[0], cipher->block_size());
cipher->encrypt(state);
send(state, cipher->block_size());
}
@@ -67,7 +67,7 @@ void CTS_Encryption::encrypt(const byte block[])
void CTS_Encryption::write(const byte input[], size_t length)
{
size_t copied = std::min<size_t>(buffer.size() - position, length);
- buffer.copy(position, input, copied);
+ buffer_insert(buffer, position, input, copied);
length -= copied;
input += copied;
position += copied;
@@ -91,7 +91,7 @@ void CTS_Encryption::write(const byte input[], size_t length)
copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size());
position = cipher->block_size();
}
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
position += length;
}
@@ -105,7 +105,7 @@ void CTS_Encryption::end_msg()
xor_buf(state, buffer, cipher->block_size());
cipher->encrypt(state);
- SecureVector<byte> cn = state;
+ secure_vector<byte> cn = state;
clear_mem(&buffer[position], buffer.size() - position);
encrypt(&buffer[cipher->block_size()]);
send(cn, position - cipher->block_size());
@@ -161,7 +161,7 @@ void CTS_Decryption::decrypt(const byte block[])
cipher->decrypt(block, &temp[0]);
xor_buf(temp, state, cipher->block_size());
send(temp, cipher->block_size());
- state.copy(block, cipher->block_size());
+ copy_mem(&state[0], block, cipher->block_size());
}
/*
@@ -170,14 +170,14 @@ void CTS_Decryption::decrypt(const byte block[])
void CTS_Decryption::write(const byte input[], size_t length)
{
size_t copied = std::min<size_t>(buffer.size() - position, length);
- buffer.copy(position, input, copied);
+ buffer_insert(buffer, position, input, copied);
length -= copied;
input += copied;
position += copied;
if(length == 0) return;
- decrypt(buffer);
+ decrypt(&buffer[0]);
if(length > cipher->block_size())
{
decrypt(&buffer[cipher->block_size()]);
@@ -194,7 +194,7 @@ void CTS_Decryption::write(const byte input[], size_t length)
copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size());
position = cipher->block_size();
}
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
position += length;
}
@@ -203,17 +203,17 @@ void CTS_Decryption::write(const byte input[], size_t length)
*/
void CTS_Decryption::end_msg()
{
- cipher->decrypt(buffer, temp);
- xor_buf(temp, &buffer[cipher->block_size()], position - cipher->block_size());
+ cipher->decrypt(&buffer[0], &temp[0]);
+ xor_buf(&temp[0], &buffer[cipher->block_size()], position - cipher->block_size());
- SecureVector<byte> xn = temp;
+ secure_vector<byte> xn = temp;
copy_mem(&buffer[position],
&xn[position - cipher->block_size()],
buffer.size() - position);
- cipher->decrypt(&buffer[cipher->block_size()], temp);
- xor_buf(temp, state, cipher->block_size());
+ cipher->decrypt(&buffer[cipher->block_size()], &temp[0]);
+ xor_buf(&temp[0], &state[0], cipher->block_size());
send(temp, cipher->block_size());
send(xn, position - cipher->block_size());
}
diff --git a/src/filters/modes/cts/cts.h b/src/filters/modes/cts/cts.h
index 8e19073f4..ac296316f 100644
--- a/src/filters/modes/cts/cts.h
+++ b/src/filters/modes/cts/cts.h
@@ -44,7 +44,7 @@ class BOTAN_DLL CTS_Encryption : public Keyed_Filter
void encrypt(const byte[]);
BlockCipher* cipher;
- SecureVector<byte> buffer, state;
+ secure_vector<byte> buffer, state;
size_t position;
};
@@ -79,7 +79,7 @@ class BOTAN_DLL CTS_Decryption : public Keyed_Filter
void decrypt(const byte[]);
BlockCipher* cipher;
- SecureVector<byte> buffer, state, temp;
+ secure_vector<byte> buffer, state, temp;
size_t position;
};
diff --git a/src/filters/modes/eax/eax.cpp b/src/filters/modes/eax/eax.cpp
index 6d6d9ec18..e67f03f68 100644
--- a/src/filters/modes/eax/eax.cpp
+++ b/src/filters/modes/eax/eax.cpp
@@ -19,7 +19,7 @@ namespace {
/*
* EAX MAC-based PRF
*/
-SecureVector<byte> eax_prf(byte tag, size_t BLOCK_SIZE,
+secure_vector<byte> eax_prf(byte tag, size_t BLOCK_SIZE,
MessageAuthenticationCode* mac,
const byte in[], size_t length)
{
@@ -45,7 +45,7 @@ EAX_Base::EAX_Base(BlockCipher* cipher, size_t tag_size) :
ctr = new CTR_BE(cipher); // takes ownership
if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->output_length())
- throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size));
+ throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size));
}
/*
@@ -70,7 +70,7 @@ void EAX_Base::set_key(const SymmetricKey& key)
ctr->set_key(key);
cmac->set_key(key);
- header_mac = eax_prf(1, BLOCK_SIZE, cmac, 0, 0);
+ header_mac = eax_prf(1, BLOCK_SIZE, cmac, nullptr, 0);
}
/*
@@ -131,7 +131,7 @@ void EAX_Encryption::write(const byte input[], size_t length)
*/
void EAX_Encryption::end_msg()
{
- SecureVector<byte> data_mac = cmac->final();
+ secure_vector<byte> data_mac = cmac->final();
xor_buf(data_mac, nonce_mac, data_mac.size());
xor_buf(data_mac, header_mac, data_mac.size());
diff --git a/src/filters/modes/eax/eax.h b/src/filters/modes/eax/eax.h
index e8efb9398..d78287521 100644
--- a/src/filters/modes/eax/eax.h
+++ b/src/filters/modes/eax/eax.h
@@ -81,17 +81,17 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter
/**
* The MAC of the nonce
*/
- SecureVector<byte> nonce_mac;
+ secure_vector<byte> nonce_mac;
/**
* The MAC of the header
*/
- SecureVector<byte> header_mac;
+ secure_vector<byte> header_mac;
/**
* A buffer for CTR mode encryption
*/
- SecureVector<byte> ctr_buf;
+ secure_vector<byte> ctr_buf;
};
/**
@@ -151,7 +151,7 @@ class BOTAN_DLL EAX_Decryption : public EAX_Base
void do_write(const byte[], size_t);
void end_msg();
- SecureVector<byte> queue;
+ secure_vector<byte> queue;
size_t queue_start, queue_end;
};
diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp
index 72e2249ac..a2675cac0 100644
--- a/src/filters/modes/eax/eax_dec.cpp
+++ b/src/filters/modes/eax/eax_dec.cpp
@@ -47,7 +47,7 @@ void EAX_Decryption::write(const byte input[], size_t length)
{
const size_t copied = std::min<size_t>(length, queue.size() - queue_end);
- queue.copy(queue_end, input, copied);
+ buffer_insert(queue, queue_end, input, copied);
input += copied;
length -= copied;
queue_end += copied;
@@ -62,9 +62,9 @@ void EAX_Decryption::write(const byte input[], size_t length)
if(queue_start + TAG_SIZE == queue_end &&
queue_start >= queue.size() / 2)
{
- SecureVector<byte> queue_data(TAG_SIZE);
- queue_data.copy(&queue[queue_start], TAG_SIZE);
- queue.copy(&queue_data[0], TAG_SIZE);
+ secure_vector<byte> queue_data(TAG_SIZE);
+ copy_mem(&queue_data[0], &queue[queue_start], TAG_SIZE);
+ copy_mem(&queue[0], &queue_data[0], TAG_SIZE);
queue_start = 0;
queue_end = TAG_SIZE;
}
@@ -100,7 +100,7 @@ void EAX_Decryption::end_msg()
if((queue_end - queue_start) != TAG_SIZE)
throw Decoding_Error(name() + ": Message authentication failure");
- SecureVector<byte> data_mac = cmac->final();
+ secure_vector<byte> data_mac = cmac->final();
for(size_t j = 0; j != TAG_SIZE; ++j)
if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j]))
diff --git a/src/filters/modes/ecb/ecb.cpp b/src/filters/modes/ecb/ecb.cpp
index 9115d6362..d36d2350b 100644
--- a/src/filters/modes/ecb/ecb.cpp
+++ b/src/filters/modes/ecb/ecb.cpp
@@ -70,8 +70,8 @@ void ECB_Encryption::end_msg()
{
size_t last_block = current_position() % cipher->block_size();
- SecureVector<byte> padding(cipher->block_size());
- padder->pad(padding, padding.size(), last_block);
+ secure_vector<byte> padding(cipher->block_size());
+ padder->pad(&padding[0], padding.size(), last_block);
size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block);
@@ -203,8 +203,8 @@ void ECB_Decryption::buffered_final(const byte input[], size_t length)
input += extra_blocks * cipher->block_size();
- cipher->decrypt(input, temp);
- send(temp, padder->unpad(temp, cipher->block_size()));
+ cipher->decrypt(input, &temp[0]);
+ send(&temp[0], padder->unpad(&temp[0], cipher->block_size()));
}
}
diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h
index 94cff1f52..e6476ab5d 100644
--- a/src/filters/modes/ecb/ecb.h
+++ b/src/filters/modes/ecb/ecb.h
@@ -46,7 +46,7 @@ class BOTAN_DLL ECB_Encryption : public Keyed_Filter,
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
- SecureVector<byte> temp;
+ secure_vector<byte> temp;
};
/**
@@ -80,7 +80,7 @@ class BOTAN_DLL ECB_Decryption : public Keyed_Filter,
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
- SecureVector<byte> temp;
+ secure_vector<byte> temp;
};
}
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp
index 2d2957088..e29ef6b98 100644
--- a/src/filters/modes/xts/xts.cpp
+++ b/src/filters/modes/xts/xts.cpp
@@ -92,14 +92,14 @@ void XTS_Encryption::set_iv(const InitializationVector& iv)
const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
- tweak.copy(iv.begin(), iv.length());
+ tweak.assign(iv.begin(), iv.end());
cipher2->encrypt(tweak);
for(size_t i = 1; i < blocks_in_tweak; ++i)
{
- tweak.copy(i*cipher->block_size(),
- &tweak[(i-1)*cipher->block_size()],
- cipher->block_size());
+ buffer_insert(tweak, i*cipher->block_size(),
+ &tweak[(i-1)*cipher->block_size()],
+ cipher->block_size());
poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
}
@@ -136,7 +136,7 @@ void XTS_Encryption::buffered_block(const byte input[], size_t length)
const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
size_t blocks = length / cipher->block_size();
- SecureVector<byte> temp(tweak.size());
+ secure_vector<byte> temp(tweak.size());
while(blocks)
{
@@ -151,13 +151,15 @@ void XTS_Encryption::buffered_block(const byte input[], size_t length)
send(temp, to_proc_bytes);
- tweak.copy(&tweak[(to_proc-1)*cipher->block_size()],
- cipher->block_size());
+ copy_mem(&tweak[0],
+ &tweak[(to_proc-1)*cipher->block_size()],
+ cipher->block_size());
+
poly_double(&tweak[0], cipher->block_size());
for(size_t i = 1; i < blocks_in_tweak; ++i)
{
- tweak.copy(i*cipher->block_size(),
+ buffer_insert(tweak, i*cipher->block_size(),
&tweak[(i-1)*cipher->block_size()],
cipher->block_size());
@@ -192,7 +194,7 @@ void XTS_Encryption::buffered_final(const byte input[], size_t length)
input += leftover_blocks;
length -= leftover_blocks;
- SecureVector<byte> temp(input, length);
+ secure_vector<byte> temp(input, input + length);
xor_buf(temp, tweak, cipher->block_size());
cipher->encrypt(temp);
@@ -264,12 +266,12 @@ void XTS_Decryption::set_iv(const InitializationVector& iv)
const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
- tweak.copy(iv.begin(), iv.length());
+ tweak.assign(iv.begin(), iv.end());
cipher2->encrypt(tweak);
for(size_t i = 1; i < blocks_in_tweak; ++i)
{
- tweak.copy(i*cipher->block_size(),
+ buffer_insert(tweak, i*cipher->block_size(),
&tweak[(i-1)*cipher->block_size()],
cipher->block_size());
@@ -309,7 +311,7 @@ void XTS_Decryption::buffered_block(const byte input[], size_t input_length)
const size_t blocks_in_tweak = tweak.size() / cipher->block_size();
size_t blocks = input_length / cipher->block_size();
- SecureVector<byte> temp(tweak.size());
+ secure_vector<byte> temp(tweak.size());
while(blocks)
{
@@ -324,15 +326,17 @@ void XTS_Decryption::buffered_block(const byte input[], size_t input_length)
send(temp, to_proc_bytes);
- tweak.copy(&tweak[(to_proc-1)*cipher->block_size()],
- cipher->block_size());
+ copy_mem(&tweak[0],
+ &tweak[(to_proc-1)*cipher->block_size()],
+ cipher->block_size());
+
poly_double(&tweak[0], cipher->block_size());
for(size_t i = 1; i < blocks_in_tweak; ++i)
{
- tweak.copy(i*cipher->block_size(),
- &tweak[(i-1)*cipher->block_size()],
- cipher->block_size());
+ buffer_insert(tweak, i*cipher->block_size(),
+ &tweak[(i-1)*cipher->block_size()],
+ cipher->block_size());
poly_double(&tweak[i*cipher->block_size()], cipher->block_size());
}
@@ -361,8 +365,8 @@ void XTS_Decryption::buffered_final(const byte input[], size_t length)
input += leftover_blocks;
length -= leftover_blocks;
- SecureVector<byte> temp(input, length);
- SecureVector<byte> tweak_copy(&tweak[0], cipher->block_size());
+ secure_vector<byte> temp(input, input + length);
+ secure_vector<byte> tweak_copy(&tweak[0], &tweak[cipher->block_size()]);
poly_double(&tweak_copy[0], cipher->block_size());
diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h
index 52db9bcfc..d4801cd37 100644
--- a/src/filters/modes/xts/xts.h
+++ b/src/filters/modes/xts/xts.h
@@ -48,7 +48,7 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter,
BlockCipher* cipher;
BlockCipher* cipher2;
- SecureVector<byte> tweak;
+ secure_vector<byte> tweak;
};
/**
@@ -85,7 +85,7 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter,
BlockCipher* cipher;
BlockCipher* cipher2;
- SecureVector<byte> tweak;
+ secure_vector<byte> tweak;
};
}
diff --git a/src/filters/out_buf.cpp b/src/filters/out_buf.cpp
index 7b79b4b70..b1dc8ff7f 100644
--- a/src/filters/out_buf.cpp
+++ b/src/filters/out_buf.cpp
@@ -69,7 +69,7 @@ void Output_Buffers::retire()
if(buffers[i] && buffers[i]->size() == 0)
{
delete buffers[i];
- buffers[i] = 0;
+ buffers[i] = nullptr;
}
while(buffers.size() && !buffers[0])
@@ -85,7 +85,7 @@ void Output_Buffers::retire()
SecureQueue* Output_Buffers::get(Pipe::message_id msg) const
{
if(msg < offset)
- return 0;
+ return nullptr;
BOTAN_ASSERT(msg < message_count(),
"Message number out of range");
diff --git a/src/filters/pipe.cpp b/src/filters/pipe.cpp
index 3c3b5e6a4..e3c2f53b6 100644
--- a/src/filters/pipe.cpp
+++ b/src/filters/pipe.cpp
@@ -43,11 +43,12 @@ Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
/*
* Pipe Constructor
*/
-Pipe::Pipe(Filter* filter_array[], size_t count)
+Pipe::Pipe(std::initializer_list<Filter*> args)
{
init();
- for(size_t j = 0; j != count; ++j)
- append(filter_array[j]);
+
+ for(auto i = args.begin(); i != args.end(); ++i)
+ append(*i);
}
/*
@@ -65,7 +66,7 @@ Pipe::~Pipe()
void Pipe::init()
{
outputs = new Output_Buffers;
- pipe = 0;
+ pipe = nullptr;
default_read = 0;
inside_msg = false;
}
@@ -75,10 +76,8 @@ void Pipe::init()
*/
void Pipe::reset()
{
- if(inside_msg)
- throw Invalid_State("Pipe cannot be reset while it is processing");
destruct(pipe);
- pipe = 0;
+ pipe = nullptr;
inside_msg = false;
}
@@ -125,7 +124,12 @@ void Pipe::process_msg(const byte input[], size_t length)
/*
* Process a full message at once
*/
-void Pipe::process_msg(const MemoryRegion<byte>& input)
+void Pipe::process_msg(const secure_vector<byte>& input)
+ {
+ process_msg(&input[0], input.size());
+ }
+
+void Pipe::process_msg(const std::vector<byte>& input)
{
process_msg(&input[0], input.size());
}
@@ -155,7 +159,7 @@ void Pipe::start_msg()
{
if(inside_msg)
throw Invalid_State("Pipe::start_msg: Message was already started");
- if(pipe == 0)
+ if(pipe == nullptr)
pipe = new Null_Filter;
find_endpoints(pipe);
pipe->new_msg();
@@ -174,7 +178,7 @@ void Pipe::end_msg()
if(dynamic_cast<Null_Filter*>(pipe))
{
delete pipe;
- pipe = 0;
+ pipe = nullptr;
}
inside_msg = false;
@@ -206,7 +210,7 @@ void Pipe::clear_endpoints(Filter* f)
for(size_t j = 0; j != f->total_ports(); ++j)
{
if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
- f->next[j] = 0;
+ f->next[j] = nullptr;
clear_endpoints(f->next[j]);
}
}
diff --git a/src/filters/pipe.h b/src/filters/pipe.h
index e5cb5f445..3236e7c36 100644
--- a/src/filters/pipe.h
+++ b/src/filters/pipe.h
@@ -11,6 +11,7 @@
#include <botan/data_src.h>
#include <botan/filter.h>
#include <botan/exceptn.h>
+#include <initializer_list>
#include <iosfwd>
namespace Botan {
@@ -42,7 +43,7 @@ class BOTAN_DLL Pipe : public DataSource
*/
Invalid_Message_Number(const std::string& where, message_id msg) :
Invalid_Argument("Pipe::" + where + ": Invalid message number " +
- to_string(msg))
+ std::to_string(msg))
{}
};
@@ -65,9 +66,17 @@ class BOTAN_DLL Pipe : public DataSource
/**
* Write input to the pipe, i.e. to its first filter.
- * @param in the MemoryRegion containing the data to write
+ * @param in the secure_vector containing the data to write
*/
- void write(const MemoryRegion<byte>& in);
+ void write(const secure_vector<byte>& in)
+ { write(&in[0], in.size()); }
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the std::vector containing the data to write
+ */
+ void write(const std::vector<byte>& in)
+ { write(&in[0], in.size()); }
/**
* Write input to the pipe, i.e. to its first filter.
@@ -96,9 +105,15 @@ class BOTAN_DLL Pipe : public DataSource
/**
* Perform start_msg(), write() and end_msg() sequentially.
- * @param in the MemoryRegion containing the data to write
+ * @param in the secure_vector containing the data to write
+ */
+ void process_msg(const secure_vector<byte>& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the secure_vector containing the data to write
*/
- void process_msg(const MemoryRegion<byte>& in);
+ void process_msg(const std::vector<byte>& in);
/**
* Perform start_msg(), write() and end_msg() sequentially.
@@ -156,9 +171,9 @@ class BOTAN_DLL Pipe : public DataSource
/**
* Read the full contents of the pipe.
* @param msg the number identifying the message to read from
- * @return SecureVector holding the contents of the pipe
+ * @return secure_vector holding the contents of the pipe
*/
- SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
+ secure_vector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
/**
* Read the full contents of the pipe.
@@ -261,18 +276,20 @@ class BOTAN_DLL Pipe : public DataSource
* Construct a Pipe of up to four filters. The filters are set up
* in the same order as the arguments.
*/
- Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+ Pipe(Filter* = nullptr, Filter* = nullptr,
+ Filter* = nullptr, Filter* = nullptr);
/**
- * Construct a Pipe from range of filters passed as an array
+ * Construct a Pipe from a list of filters
* @param filters the set of filters to use
- * @param count the number of elements in filters
*/
- Pipe(Filter* filters[], size_t count);
+ Pipe(std::initializer_list<Filter*> filters);
+
+ Pipe(const Pipe&) = delete;
+ Pipe& operator=(const Pipe&) = delete;
+
~Pipe();
private:
- Pipe(const Pipe&) : DataSource() {}
- Pipe& operator=(const Pipe&) { return (*this); }
void init();
void destruct(Filter*);
void find_endpoints(Filter*);
diff --git a/src/filters/pipe_io.cpp b/src/filters/pipe_io.cpp
index 9dd0ad0bb..a549eaee8 100644
--- a/src/filters/pipe_io.cpp
+++ b/src/filters/pipe_io.cpp
@@ -15,7 +15,7 @@ namespace Botan {
*/
std::ostream& operator<<(std::ostream& stream, Pipe& pipe)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(stream.good() && pipe.remaining())
{
size_t got = pipe.read(&buffer[0], buffer.size());
@@ -31,7 +31,7 @@ std::ostream& operator<<(std::ostream& stream, Pipe& pipe)
*/
std::istream& operator>>(std::istream& stream, Pipe& pipe)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(stream.good())
{
stream.read(reinterpret_cast<char*>(&buffer[0]), buffer.size());
diff --git a/src/filters/pipe_rw.cpp b/src/filters/pipe_rw.cpp
index 90af9ed34..8a713ea8d 100644
--- a/src/filters/pipe_rw.cpp
+++ b/src/filters/pipe_rw.cpp
@@ -39,14 +39,6 @@ void Pipe::write(const byte input[], size_t length)
}
/*
-* Write into a Pipe
-*/
-void Pipe::write(const MemoryRegion<byte>& input)
- {
- write(&input[0], input.size());
- }
-
-/*
* Write a string into a Pipe
*/
void Pipe::write(const std::string& str)
@@ -67,7 +59,7 @@ void Pipe::write(byte input)
*/
void Pipe::write(DataSource& source)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(!source.end_of_data())
{
size_t got = source.read(&buffer[0], buffer.size());
@@ -102,10 +94,10 @@ size_t Pipe::read(byte& out, message_id msg)
/*
* Return all data in the pipe
*/
-SecureVector<byte> Pipe::read_all(message_id msg)
+secure_vector<byte> Pipe::read_all(message_id msg)
{
msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
- SecureVector<byte> buffer(remaining(msg));
+ secure_vector<byte> buffer(remaining(msg));
size_t got = read(&buffer[0], buffer.size(), msg);
buffer.resize(got);
return buffer;
@@ -117,7 +109,7 @@ SecureVector<byte> Pipe::read_all(message_id msg)
std::string Pipe::read_all_as_string(message_id msg)
{
msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
std::string str;
str.reserve(remaining(msg));
diff --git a/src/filters/pk_filts/pk_filts.cpp b/src/filters/pk_filts/pk_filts.cpp
index d843d711c..45fcc18b8 100644
--- a/src/filters/pk_filts/pk_filts.cpp
+++ b/src/filters/pk_filts/pk_filts.cpp
@@ -83,14 +83,13 @@ void PK_Verifier_Filter::end_msg()
*/
void PK_Verifier_Filter::set_signature(const byte sig[], size_t length)
{
- signature.resize(length);
- copy_mem(&signature[0], sig, length);
+ signature.assign(sig, sig + length);
}
/*
* Set the signature to check
*/
-void PK_Verifier_Filter::set_signature(const MemoryRegion<byte>& sig)
+void PK_Verifier_Filter::set_signature(const secure_vector<byte>& sig)
{
signature = sig;
}
@@ -100,7 +99,7 @@ void PK_Verifier_Filter::set_signature(const MemoryRegion<byte>& sig)
*/
PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[],
size_t length) :
- verifier(v), signature(sig, length)
+ verifier(v), signature(sig, sig + length)
{
}
@@ -108,7 +107,7 @@ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[],
* PK_Verifier_Filter Constructor
*/
PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v,
- const MemoryRegion<byte>& sig) :
+ const secure_vector<byte>& sig) :
verifier(v), signature(sig)
{
}
diff --git a/src/filters/pk_filts/pk_filts.h b/src/filters/pk_filts/pk_filts.h
index dd67e389b..cc1c2220d 100644
--- a/src/filters/pk_filts/pk_filts.h
+++ b/src/filters/pk_filts/pk_filts.h
@@ -28,7 +28,7 @@ class BOTAN_DLL PK_Encryptor_Filter : public Filter
private:
PK_Encryptor* cipher;
RandomNumberGenerator& rng;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
};
/**
@@ -43,7 +43,7 @@ class BOTAN_DLL PK_Decryptor_Filter : public Filter
~PK_Decryptor_Filter() { delete cipher; }
private:
PK_Decryptor* cipher;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
};
/**
@@ -75,15 +75,15 @@ class BOTAN_DLL PK_Verifier_Filter : public Filter
void end_msg();
void set_signature(const byte[], size_t);
- void set_signature(const MemoryRegion<byte>&);
+ void set_signature(const secure_vector<byte>&);
PK_Verifier_Filter(PK_Verifier* v) : verifier(v) {}
PK_Verifier_Filter(PK_Verifier*, const byte[], size_t);
- PK_Verifier_Filter(PK_Verifier*, const MemoryRegion<byte>&);
+ PK_Verifier_Filter(PK_Verifier*, const secure_vector<byte>&);
~PK_Verifier_Filter() { delete verifier; }
private:
PK_Verifier* verifier;
- SecureVector<byte> signature;
+ secure_vector<byte> signature;
};
}
diff --git a/src/filters/secqueue.cpp b/src/filters/secqueue.cpp
index 8dc95ea99..811a7ef57 100644
--- a/src/filters/secqueue.cpp
+++ b/src/filters/secqueue.cpp
@@ -17,9 +17,9 @@ class SecureQueueNode
{
public:
SecureQueueNode() : buffer(DEFAULT_BUFFERSIZE)
- { next = 0; start = end = 0; }
+ { next = nullptr; start = end = 0; }
- ~SecureQueueNode() { next = 0; start = end = 0; }
+ ~SecureQueueNode() { next = nullptr; start = end = 0; }
size_t write(const byte input[], size_t length)
{
@@ -50,7 +50,7 @@ class SecureQueueNode
private:
friend class SecureQueue;
SecureQueueNode* next;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
size_t start, end;
};
@@ -59,7 +59,7 @@ class SecureQueueNode
*/
SecureQueue::SecureQueue()
{
- set_next(0, 0);
+ set_next(nullptr, 0);
head = tail = new SecureQueueNode;
}
@@ -69,7 +69,7 @@ SecureQueue::SecureQueue()
SecureQueue::SecureQueue(const SecureQueue& input) :
Fanout_Filter(), DataSource()
{
- set_next(0, 0);
+ set_next(nullptr, 0);
head = tail = new SecureQueueNode;
SecureQueueNode* temp = input.head;
@@ -92,7 +92,7 @@ void SecureQueue::destroy()
delete temp;
temp = holder;
}
- head = tail = 0;
+ head = tail = nullptr;
}
/*
@@ -208,4 +208,9 @@ bool SecureQueue::end_of_data() const
return (size() == 0);
}
+bool SecureQueue::empty() const
+ {
+ return (size() == 0);
+ }
+
}
diff --git a/src/filters/secqueue.h b/src/filters/secqueue.h
index 632ae857d..e773b69bc 100644
--- a/src/filters/secqueue.h
+++ b/src/filters/secqueue.h
@@ -28,6 +28,8 @@ class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
bool end_of_data() const;
+ bool empty() const;
+
/**
* @return number of bytes available in the queue
*/
diff --git a/src/filters/zlib/zlib.cpp b/src/filters/zlib/zlib.cpp
index 0f88b5558..169146826 100644
--- a/src/filters/zlib/zlib.cpp
+++ b/src/filters/zlib/zlib.cpp
@@ -47,7 +47,7 @@ void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size)
void zlib_free(void* info_ptr, void* ptr)
{
Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
- std::map<void*, size_t>::const_iterator i = info->current_allocs.find(ptr);
+ auto i = info->current_allocs.find(ptr);
if(i == info->current_allocs.end())
throw Invalid_Argument("zlib_free: Got pointer not allocated by us");
info->alloc->deallocate(ptr, i->second);
@@ -91,10 +91,12 @@ class Zlib_Stream
/*
* Zlib_Compression Constructor
*/
-Zlib_Compression::Zlib_Compression(size_t l) :
- level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+Zlib_Compression::Zlib_Compression(size_t l, bool raw_deflate) :
+ level((l >= 9) ? 9 : l),
+ raw_deflate(raw_deflate),
+ buffer(DEFAULT_BUFFERSIZE),
+ zlib(0)
{
- zlib = 0;
}
/*
@@ -104,7 +106,17 @@ void Zlib_Compression::start_msg()
{
clear();
zlib = new Zlib_Stream;
- if(deflateInit(&(zlib->stream), level) != Z_OK)
+
+ int res = deflateInit2(&(zlib->stream),
+ level,
+ Z_DEFLATED,
+ (raw_deflate ? -15 : 15),
+ 8,
+ Z_DEFAULT_STRATEGY);
+
+ if(res == Z_STREAM_ERROR)
+ throw Invalid_Argument("Bad setting in deflateInit2");
+ else if(res != Z_OK)
throw Memory_Exhaustion();
}
@@ -185,10 +197,12 @@ void Zlib_Compression::clear()
/*
* Zlib_Decompression Constructor
*/
-Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE)
+Zlib_Decompression::Zlib_Decompression(bool raw_deflate) :
+ raw_deflate(raw_deflate),
+ buffer(DEFAULT_BUFFERSIZE),
+ zlib(0),
+ no_writes(true)
{
- zlib = 0;
- no_writes = true;
}
/*
@@ -198,7 +212,8 @@ void Zlib_Decompression::start_msg()
{
clear();
zlib = new Zlib_Stream;
- if(inflateInit(&(zlib->stream)) != Z_OK)
+
+ if(inflateInit2(&(zlib->stream), (raw_deflate ? -15 : 15)) != Z_OK)
throw Memory_Exhaustion();
}
diff --git a/src/filters/zlib/zlib.h b/src/filters/zlib/zlib.h
index 77ec5eecc..c4d21a250 100644
--- a/src/filters/zlib/zlib.h
+++ b/src/filters/zlib/zlib.h
@@ -31,16 +31,21 @@ class BOTAN_DLL Zlib_Compression : public Filter
void flush();
/**
- @param level how much effort to use on compressing (0 to 9);
- higher levels are slower but tend to give better compression
+ * @param level how much effort to use on compressing (0 to 9);
+ * higher levels are slower but tend to give better
+ * compression
+ * @param raw_deflate if true no zlib header/trailer will be used
*/
- Zlib_Compression(size_t level = 6);
+ Zlib_Compression(size_t level = 6,
+ bool raw_deflate = false);
~Zlib_Compression() { clear(); }
private:
void clear();
const size_t level;
- SecureVector<byte> buffer;
+ const bool raw_deflate;
+
+ secure_vector<byte> buffer;
class Zlib_Stream* zlib;
};
@@ -56,11 +61,14 @@ class BOTAN_DLL Zlib_Decompression : public Filter
void start_msg();
void end_msg();
- Zlib_Decompression();
+ Zlib_Decompression(bool raw_deflate = false);
~Zlib_Decompression() { clear(); }
private:
void clear();
- SecureVector<byte> buffer;
+
+ const bool raw_deflate;
+
+ secure_vector<byte> buffer;
class Zlib_Stream* zlib;
bool no_writes;
};
diff --git a/src/hash/bmw_512/bmw_512.h b/src/hash/bmw_512/bmw_512.h
index 474b607bb..b9ea63578 100644
--- a/src/hash/bmw_512/bmw_512.h
+++ b/src/hash/bmw_512/bmw_512.h
@@ -30,7 +30,7 @@ class BOTAN_DLL BMW_512 : public MDx_HashFunction
void compress_n(const byte input[], size_t blocks);
void copy_out(byte output[]);
- SecureVector<u64bit> H, M, Q;
+ secure_vector<u64bit> H, M, Q;
};
}
diff --git a/src/hash/comb4p/comb4p.cpp b/src/hash/comb4p/comb4p.cpp
index 1ea64a5cb..7aec5972e 100644
--- a/src/hash/comb4p/comb4p.cpp
+++ b/src/hash/comb4p/comb4p.cpp
@@ -13,8 +13,8 @@ namespace Botan {
namespace {
-void comb4p_round(MemoryRegion<byte>& out,
- const MemoryRegion<byte>& in,
+void comb4p_round(secure_vector<byte>& out,
+ const secure_vector<byte>& in,
byte round_no,
HashFunction* h1,
HashFunction* h2)
@@ -25,7 +25,7 @@ void comb4p_round(MemoryRegion<byte>& out,
h1->update(&in[0], in.size());
h2->update(&in[0], in.size());
- SecureVector<byte> h_buf = h1->final();
+ secure_vector<byte> h_buf = h1->final();
xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size()));
h_buf = h2->final();
@@ -78,8 +78,8 @@ void Comb4P::add_data(const byte input[], size_t length)
void Comb4P::final_result(byte out[])
{
- SecureVector<byte> h1 = hash1->final();
- SecureVector<byte> h2 = hash2->final();
+ secure_vector<byte> h1 = hash1->final();
+ secure_vector<byte> h2 = hash2->final();
// First round
xor_buf(&h1[0], &h2[0], std::min(h1.size(), h2.size()));
diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp
index c0f39da47..eb889c0a5 100644
--- a/src/hash/gost_3411/gost_3411.cpp
+++ b/src/hash/gost_3411/gost_3411.cpp
@@ -43,7 +43,7 @@ void GOST_34_11::add_data(const byte input[], size_t length)
if(position)
{
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
if(position + length >= hash_block_size())
{
@@ -60,7 +60,7 @@ void GOST_34_11::add_data(const byte input[], size_t length)
if(full_blocks)
compress_n(input, full_blocks);
- buffer.copy(position, input + full_blocks * hash_block_size(), remaining);
+ buffer_insert(buffer, position, input + full_blocks * hash_block_size(), remaining);
position += remaining;
}
@@ -210,7 +210,7 @@ void GOST_34_11::compress_n(const byte input[], size_t blocks)
S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30];
S2[31] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[15] ^ S[17] ^ S[19] ^ S[23] ^ S[25] ^ S[29] ^ S[31];
- hash.copy(S2, 32);
+ copy_mem(&hash[0], &S2[0], 32);
}
}
@@ -225,11 +225,11 @@ void GOST_34_11::final_result(byte out[])
compress_n(&buffer[0], 1);
}
- SecureVector<byte> length_buf(32);
+ secure_vector<byte> length_buf(32);
const u64bit bit_count = count * 8;
store_le(bit_count, &length_buf[0]);
- SecureVector<byte> sum_buf = sum;
+ secure_vector<byte> sum_buf = sum;
compress_n(&length_buf[0], 1);
compress_n(&sum_buf[0], 1);
diff --git a/src/hash/gost_3411/gost_3411.h b/src/hash/gost_3411/gost_3411.h
index fbbcb7a89..5437ca4d8 100644
--- a/src/hash/gost_3411/gost_3411.h
+++ b/src/hash/gost_3411/gost_3411.h
@@ -34,7 +34,7 @@ class BOTAN_DLL GOST_34_11 : public HashFunction
void final_result(byte[]);
GOST_28147_89 cipher;
- SecureVector<byte> buffer, sum, hash;
+ secure_vector<byte> buffer, sum, hash;
size_t position;
u64bit count;
};
diff --git a/src/hash/has160/has160.h b/src/hash/has160/has160.h
index d32361601..9947d9580 100644
--- a/src/hash/has160/has160.h
+++ b/src/hash/has160/has160.h
@@ -31,7 +31,7 @@ class BOTAN_DLL HAS_160 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> X, digest;
+ secure_vector<u32bit> X, digest;
};
}
diff --git a/src/hash/keccak/keccak.cpp b/src/hash/keccak/keccak.cpp
index 922167b61..e34c0fd43 100644
--- a/src/hash/keccak/keccak.cpp
+++ b/src/hash/keccak/keccak.cpp
@@ -112,12 +112,12 @@ Keccak_1600::Keccak_1600(size_t output_bits) :
if(output_bits != 224 && output_bits != 256 &&
output_bits != 384 && output_bits != 512)
throw Invalid_Argument("Keccak_1600: Invalid output length " +
- to_string(output_bits));
+ std::to_string(output_bits));
}
std::string Keccak_1600::name() const
{
- return "Keccak-1600(" + to_string(output_bits) + ")";
+ return "Keccak-1600(" + std::to_string(output_bits) + ")";
}
HashFunction* Keccak_1600::clone() const
@@ -178,12 +178,12 @@ void Keccak_1600::add_data(const byte input[], size_t length)
void Keccak_1600::final_result(byte output[])
{
- MemoryVector<byte> padding(bitrate / 8 - S_pos);
+ std::vector<byte> padding(bitrate / 8 - S_pos);
padding[0] = 0x01;
padding[padding.size()-1] |= 0x80;
- add_data(padding, padding.size());
+ add_data(&padding[0], padding.size());
/*
* We never have to run the permutation again because we only support
diff --git a/src/hash/keccak/keccak.h b/src/hash/keccak/keccak.h
index 17ae632ba..e91a04d32 100644
--- a/src/hash/keccak/keccak.h
+++ b/src/hash/keccak/keccak.h
@@ -38,7 +38,7 @@ class BOTAN_DLL Keccak_1600 : public HashFunction
void final_result(byte out[]);
size_t output_bits, bitrate;
- SecureVector<u64bit> S;
+ secure_vector<u64bit> S;
size_t S_pos;
};
diff --git a/src/hash/md2/md2.cpp b/src/hash/md2/md2.cpp
index 761528dc6..8f6a90208 100644
--- a/src/hash/md2/md2.cpp
+++ b/src/hash/md2/md2.cpp
@@ -39,7 +39,7 @@ void MD2::hash(const byte input[])
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33,
0x9F, 0x11, 0x83, 0x14 };
- X.copy(16, input, hash_block_size());
+ buffer_insert(X, 16, input, hash_block_size());
xor_buf(&X[32], &X[0], &X[16], hash_block_size());
byte T = 0;
@@ -66,7 +66,7 @@ void MD2::hash(const byte input[])
*/
void MD2::add_data(const byte input[], size_t length)
{
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
if(position + length >= hash_block_size())
{
@@ -79,7 +79,7 @@ void MD2::add_data(const byte input[], size_t length)
input += hash_block_size();
length -= hash_block_size();
}
- buffer.copy(input, length);
+ copy_mem(&buffer[0], input, length);
position = 0;
}
position += length;
diff --git a/src/hash/md2/md2.h b/src/hash/md2/md2.h
index 84e0323f7..032d8a8e0 100644
--- a/src/hash/md2/md2.h
+++ b/src/hash/md2/md2.h
@@ -32,7 +32,7 @@ class BOTAN_DLL MD2 : public HashFunction
void hash(const byte[]);
void final_result(byte[]);
- SecureVector<byte> X, checksum, buffer;
+ secure_vector<byte> X, checksum, buffer;
size_t position;
};
diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h
index d37dbe3b2..750be0fe7 100644
--- a/src/hash/md4/md4.h
+++ b/src/hash/md4/md4.h
@@ -33,12 +33,12 @@ class BOTAN_DLL MD4 : public MDx_HashFunction
/**
* The message buffer, exposed for use by subclasses (x86 asm)
*/
- SecureVector<u32bit> M;
+ secure_vector<u32bit> M;
/**
* The digest value, exposed for use by subclasses (x86 asm)
*/
- SecureVector<u32bit> digest;
+ secure_vector<u32bit> digest;
};
}
diff --git a/src/hash/md5/md5.h b/src/hash/md5/md5.h
index 92c023c92..bc90df0af 100644
--- a/src/hash/md5/md5.h
+++ b/src/hash/md5/md5.h
@@ -33,12 +33,12 @@ class BOTAN_DLL MD5 : public MDx_HashFunction
/**
* The message buffer, exposed for use by subclasses (x86 asm)
*/
- SecureVector<u32bit> M;
+ secure_vector<u32bit> M;
/**
* The digest value, exposed for use by subclasses (x86 asm)
*/
- SecureVector<u32bit> digest;
+ secure_vector<u32bit> digest;
};
}
diff --git a/src/hash/mdx_hash/mdx_hash.cpp b/src/hash/mdx_hash/mdx_hash.cpp
index 7bfcf6592..81042c1fa 100644
--- a/src/hash/mdx_hash/mdx_hash.cpp
+++ b/src/hash/mdx_hash/mdx_hash.cpp
@@ -44,7 +44,7 @@ void MDx_HashFunction::add_data(const byte input[], size_t length)
if(position)
{
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
if(position + length >= buffer.size())
{
@@ -61,7 +61,7 @@ void MDx_HashFunction::add_data(const byte input[], size_t length)
if(full_blocks)
compress_n(input, full_blocks);
- buffer.copy(position, input + full_blocks * buffer.size(), remaining);
+ buffer_insert(buffer, position, input + full_blocks * buffer.size(), remaining);
position += remaining;
}
diff --git a/src/hash/mdx_hash/mdx_hash.h b/src/hash/mdx_hash/mdx_hash.h
index ed3381605..14d3c27a0 100644
--- a/src/hash/mdx_hash/mdx_hash.h
+++ b/src/hash/mdx_hash/mdx_hash.h
@@ -55,7 +55,7 @@ class BOTAN_DLL MDx_HashFunction : public HashFunction
*/
virtual void write_count(byte out[]);
private:
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
u64bit count;
size_t position;
diff --git a/src/hash/par_hash/par_hash.cpp b/src/hash/par_hash/par_hash.cpp
index 328be6a11..df47780ef 100644
--- a/src/hash/par_hash/par_hash.cpp
+++ b/src/hash/par_hash/par_hash.cpp
@@ -1,11 +1,12 @@
/*
* Parallel
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/par_hash.h>
+#include <botan/parsing.h>
namespace Botan {
@@ -14,20 +15,21 @@ namespace Botan {
*/
void Parallel::add_data(const byte input[], size_t length)
{
- for(size_t i = 0; i != hashes.size(); ++i)
- hashes[i]->update(input, length);
+ for(auto hash : hashes)
+ hash->update(input, length);
}
/*
* Finalize the hash
*/
-void Parallel::final_result(byte hash[])
+void Parallel::final_result(byte out[])
{
- size_t offset = 0;
- for(size_t i = 0; i != hashes.size(); ++i)
+ u32bit offset = 0;
+
+ for(auto hash : hashes)
{
- hashes[i]->final(hash + offset);
- offset += hashes[i]->output_length();
+ hash->final(out + offset);
+ offset += hash->output_length();
}
}
@@ -37,8 +39,9 @@ void Parallel::final_result(byte hash[])
size_t Parallel::output_length() const
{
size_t sum = 0;
- for(size_t i = 0; i != hashes.size(); ++i)
- sum += hashes[i]->output_length();
+
+ for(auto hash : hashes)
+ sum += hash->output_length();
return sum;
}
@@ -47,14 +50,12 @@ size_t Parallel::output_length() const
*/
std::string Parallel::name() const
{
- std::string hash_names;
- for(size_t i = 0; i != hashes.size(); ++i)
- {
- if(i)
- hash_names += ',';
- hash_names += hashes[i]->name();
- }
- return "Parallel(" + hash_names + ")";
+ std::vector<std::string> names;
+
+ for(auto hash : hashes)
+ names.push_back(hash->name());
+
+ return "Parallel(" + string_join(names, ',') + ")";
}
/*
@@ -63,8 +64,10 @@ std::string Parallel::name() const
HashFunction* Parallel::clone() const
{
std::vector<HashFunction*> hash_copies;
- for(size_t i = 0; i != hashes.size(); ++i)
- hash_copies.push_back(hashes[i]->clone());
+
+ for(auto hash : hashes)
+ hash_copies.push_back(hash->clone());
+
return new Parallel(hash_copies);
}
@@ -73,8 +76,8 @@ HashFunction* Parallel::clone() const
*/
void Parallel::clear()
{
- for(size_t i = 0; i != hashes.size(); ++i)
- hashes[i]->clear();
+ for(auto hash : hashes)
+ hash->clear();
}
/*
@@ -90,8 +93,8 @@ Parallel::Parallel(const std::vector<HashFunction*>& hash_in) :
*/
Parallel::~Parallel()
{
- for(size_t i = 0; i != hashes.size(); ++i)
- delete hashes[i];
+ for(auto hash : hashes)
+ delete hash;
}
}
diff --git a/src/hash/rmd128/rmd128.h b/src/hash/rmd128/rmd128.h
index d64cf3c84..e37666a27 100644
--- a/src/hash/rmd128/rmd128.h
+++ b/src/hash/rmd128/rmd128.h
@@ -30,7 +30,7 @@ class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> M, digest;
+ secure_vector<u32bit> M, digest;
};
}
diff --git a/src/hash/rmd160/rmd160.h b/src/hash/rmd160/rmd160.h
index 5df4ad490..0e43fed9a 100644
--- a/src/hash/rmd160/rmd160.h
+++ b/src/hash/rmd160/rmd160.h
@@ -30,7 +30,7 @@ class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> M, digest;
+ secure_vector<u32bit> M, digest;
};
}
diff --git a/src/hash/sha1/sha160.h b/src/hash/sha1/sha160.h
index c3b264861..e2a81808d 100644
--- a/src/hash/sha1/sha160.h
+++ b/src/hash/sha1/sha160.h
@@ -47,12 +47,12 @@ class BOTAN_DLL SHA_160 : public MDx_HashFunction
/**
* The digest value, exposed for use by subclasses (asm, SSE2)
*/
- SecureVector<u32bit> digest;
+ secure_vector<u32bit> digest;
/**
* The message buffer, exposed for use by subclasses (asm, SSE2)
*/
- SecureVector<u32bit> W;
+ secure_vector<u32bit> W;
};
}
diff --git a/src/hash/sha2_32/sha2_32.cpp b/src/hash/sha2_32/sha2_32.cpp
index 6dd780e64..cffc8bd2a 100644
--- a/src/hash/sha2_32/sha2_32.cpp
+++ b/src/hash/sha2_32/sha2_32.cpp
@@ -50,7 +50,7 @@ inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift)
/*
* SHA-224 / SHA-256 compression function
*/
-void compress(MemoryRegion<u32bit>& digest,
+void compress(secure_vector<u32bit>& digest,
const byte input[], size_t blocks)
{
u32bit A = digest[0], B = digest[1], C = digest[2],
diff --git a/src/hash/sha2_32/sha2_32.h b/src/hash/sha2_32/sha2_32.h
index 807b979d1..ccb8e07f2 100644
--- a/src/hash/sha2_32/sha2_32.h
+++ b/src/hash/sha2_32/sha2_32.h
@@ -31,7 +31,7 @@ class BOTAN_DLL SHA_224 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> digest;
+ secure_vector<u32bit> digest;
};
/**
@@ -52,7 +52,7 @@ class BOTAN_DLL SHA_256 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> digest;
+ secure_vector<u32bit> digest;
};
}
diff --git a/src/hash/sha2_64/sha2_64.cpp b/src/hash/sha2_64/sha2_64.cpp
index 3026c3a39..8dcb4684e 100644
--- a/src/hash/sha2_64/sha2_64.cpp
+++ b/src/hash/sha2_64/sha2_64.cpp
@@ -49,7 +49,7 @@ inline u64bit sigma(u64bit X, u32bit rot1, u32bit rot2, u32bit shift)
/*
* SHA-{384,512} Compression Function
*/
-void compress(MemoryRegion<u64bit>& digest,
+void compress(secure_vector<u64bit>& digest,
const byte input[], size_t blocks)
{
u64bit A = digest[0], B = digest[1], C = digest[2],
diff --git a/src/hash/sha2_64/sha2_64.h b/src/hash/sha2_64/sha2_64.h
index 124d4bbfb..58b154170 100644
--- a/src/hash/sha2_64/sha2_64.h
+++ b/src/hash/sha2_64/sha2_64.h
@@ -30,7 +30,7 @@ class BOTAN_DLL SHA_384 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u64bit> digest;
+ secure_vector<u64bit> digest;
};
/**
@@ -51,7 +51,7 @@ class BOTAN_DLL SHA_512 : public MDx_HashFunction
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u64bit> digest;
+ secure_vector<u64bit> digest;
};
}
diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp
index 571bf9c0b..28c2aa38b 100644
--- a/src/hash/skein/skein_512.cpp
+++ b/src/hash/skein/skein_512.cpp
@@ -27,8 +27,8 @@ enum type_code {
SKEIN_OUTPUT = 63
};
-void ubi_512(MemoryRegion<u64bit>& H,
- MemoryRegion<u64bit>& T,
+void ubi_512(secure_vector<u64bit>& H,
+ secure_vector<u64bit>& T,
const byte msg[], size_t msg_len)
{
do
@@ -125,7 +125,7 @@ void ubi_512(MemoryRegion<u64bit>& H,
} while(msg_len);
}
-void reset_tweak(MemoryRegion<u64bit>& T,
+void reset_tweak(secure_vector<u64bit>& T,
type_code type, bool final)
{
T[0] = 0;
@@ -135,8 +135,8 @@ void reset_tweak(MemoryRegion<u64bit>& T,
(static_cast<u64bit>(final) << 63);
}
-void initial_block(MemoryRegion<u64bit>& H,
- MemoryRegion<u64bit>& T,
+void initial_block(secure_vector<u64bit>& H,
+ secure_vector<u64bit>& T,
size_t output_bits,
const std::string& personalization)
{
@@ -185,8 +185,9 @@ Skein_512::Skein_512(size_t arg_output_bits,
std::string Skein_512::name() const
{
if(personalization != "")
- return "Skein-512(" + to_string(output_bits) + "," + personalization + ")";
- return "Skein-512(" + to_string(output_bits) + ")";
+ return "Skein-512(" + std::to_string(output_bits) + "," +
+ personalization + ")";
+ return "Skein-512(" + std::to_string(output_bits) + ")";
}
HashFunction* Skein_512::clone() const
@@ -209,7 +210,7 @@ void Skein_512::add_data(const byte input[], size_t length)
if(buf_pos)
{
- buffer.copy(buf_pos, input, length);
+ buffer_insert(buffer, buf_pos, input, length);
if(buf_pos + length > 64)
{
ubi_512(H, T, &buffer[0], buffer.size());
@@ -227,7 +228,7 @@ void Skein_512::add_data(const byte input[], size_t length)
length -= full_blocks * 64;
- buffer.copy(buf_pos, input + full_blocks * 64, length);
+ buffer_insert(buffer, buf_pos, input + full_blocks * 64, length);
buf_pos += length;
}
@@ -244,13 +245,13 @@ void Skein_512::final_result(byte out[])
size_t out_bytes = output_bits / 8;
- SecureVector<u64bit> H_out(9);
+ secure_vector<u64bit> H_out(9);
while(out_bytes)
{
const size_t to_proc = std::min<size_t>(out_bytes, 64);
- H_out.copy(&H[0], 8);
+ copy_mem(&H_out[0], &H[0], 8);
reset_tweak(T, SKEIN_OUTPUT, true);
ubi_512(H_out, T, counter, sizeof(counter));
diff --git a/src/hash/skein/skein_512.h b/src/hash/skein/skein_512.h
index 8605e5991..e0abc06ae 100644
--- a/src/hash/skein/skein_512.h
+++ b/src/hash/skein/skein_512.h
@@ -41,9 +41,9 @@ class BOTAN_DLL Skein_512 : public HashFunction
std::string personalization;
size_t output_bits;
- SecureVector<u64bit> H;
- SecureVector<u64bit> T;
- SecureVector<byte> buffer;
+ secure_vector<u64bit> H;
+ secure_vector<u64bit> T;
+ secure_vector<byte> buffer;
size_t buf_pos;
};
diff --git a/src/hash/tiger/tiger.cpp b/src/hash/tiger/tiger.cpp
index 6f40f84c8..57250d6f5 100644
--- a/src/hash/tiger/tiger.cpp
+++ b/src/hash/tiger/tiger.cpp
@@ -17,7 +17,7 @@ namespace {
/*
* Tiger Mixing Function
*/
-inline void mix(MemoryRegion<u64bit>& X)
+inline void mix(secure_vector<u64bit>& X)
{
X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5;
X[1] ^= X[0];
@@ -83,7 +83,7 @@ void Tiger::copy_out(byte output[])
* Tiger Pass
*/
void Tiger::pass(u64bit& A, u64bit& B, u64bit& C,
- const MemoryRegion<u64bit>& X,
+ const secure_vector<u64bit>& X,
byte mul)
{
C ^= X[0];
@@ -160,7 +160,8 @@ void Tiger::clear()
*/
std::string Tiger::name() const
{
- return "Tiger(" + to_string(output_length()) + "," + to_string(passes) + ")";
+ return "Tiger(" + std::to_string(output_length()) + "," +
+ std::to_string(passes) + ")";
}
/*
@@ -175,11 +176,11 @@ Tiger::Tiger(size_t hash_len, size_t passes) :
{
if(output_length() != 16 && output_length() != 20 && output_length() != 24)
throw Invalid_Argument("Tiger: Illegal hash output size: " +
- to_string(output_length()));
+ std::to_string(output_length()));
if(passes < 3)
throw Invalid_Argument("Tiger: Invalid number of passes: "
- + to_string(passes));
+ + std::to_string(passes));
clear();
}
diff --git a/src/hash/tiger/tiger.h b/src/hash/tiger/tiger.h
index 09c9947fb..70c70958b 100644
--- a/src/hash/tiger/tiger.h
+++ b/src/hash/tiger/tiger.h
@@ -38,7 +38,7 @@ class BOTAN_DLL Tiger : public MDx_HashFunction
void copy_out(byte[]);
static void pass(u64bit& A, u64bit& B, u64bit& C,
- const MemoryRegion<u64bit>& M,
+ const secure_vector<u64bit>& M,
byte mul);
static const u64bit SBOX1[256];
@@ -46,7 +46,7 @@ class BOTAN_DLL Tiger : public MDx_HashFunction
static const u64bit SBOX3[256];
static const u64bit SBOX4[256];
- SecureVector<u64bit> X, digest;
+ secure_vector<u64bit> X, digest;
const size_t hash_len, passes;
};
diff --git a/src/hash/whirlpool/whrlpool.h b/src/hash/whirlpool/whrlpool.h
index ab7a78bc8..d4ad805e1 100644
--- a/src/hash/whirlpool/whrlpool.h
+++ b/src/hash/whirlpool/whrlpool.h
@@ -39,7 +39,7 @@ class BOTAN_DLL Whirlpool : public MDx_HashFunction
static const u64bit C6[256];
static const u64bit C7[256];
- SecureVector<u64bit> M, digest;
+ secure_vector<u64bit> M, digest;
};
}
diff --git a/src/kdf/kdf.cpp b/src/kdf/kdf.cpp
index 6281f753c..88cbd5b99 100644
--- a/src/kdf/kdf.cpp
+++ b/src/kdf/kdf.cpp
@@ -12,8 +12,8 @@ namespace Botan {
/*
* Derive a key
*/
-SecureVector<byte> KDF::derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
+secure_vector<byte> KDF::derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
const std::string& salt) const
{
return derive_key(key_len, &secret[0], secret.size(),
@@ -24,8 +24,8 @@ SecureVector<byte> KDF::derive_key(size_t key_len,
/*
* Derive a key
*/
-SecureVector<byte> KDF::derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
+secure_vector<byte> KDF::derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
const byte salt[], size_t salt_len) const
{
return derive_key(key_len, &secret[0], secret.size(),
@@ -35,18 +35,7 @@ SecureVector<byte> KDF::derive_key(size_t key_len,
/*
* Derive a key
*/
-SecureVector<byte> KDF::derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
- const MemoryRegion<byte>& salt) const
- {
- return derive_key(key_len, &secret[0], secret.size(),
- &salt[0], salt.size());
- }
-
-/*
-* Derive a key
-*/
-SecureVector<byte> KDF::derive_key(size_t key_len,
+secure_vector<byte> KDF::derive_key(size_t key_len,
const byte secret[], size_t secret_len,
const std::string& salt) const
{
@@ -58,7 +47,7 @@ SecureVector<byte> KDF::derive_key(size_t key_len,
/*
* Derive a key
*/
-SecureVector<byte> KDF::derive_key(size_t key_len,
+secure_vector<byte> KDF::derive_key(size_t key_len,
const byte secret[], size_t secret_len,
const byte salt[], size_t salt_len) const
{
diff --git a/src/kdf/kdf.h b/src/kdf/kdf.h
index 3ec912cfe..e158df0ae 100644
--- a/src/kdf/kdf.h
+++ b/src/kdf/kdf.h
@@ -26,8 +26,8 @@ class BOTAN_DLL KDF : public Algorithm
* @param secret the secret input
* @param salt a diversifier
*/
- SecureVector<byte> derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
+ secure_vector<byte> derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
const std::string& salt = "") const;
/**
@@ -36,9 +36,15 @@ class BOTAN_DLL KDF : public Algorithm
* @param secret the secret input
* @param salt a diversifier
*/
- SecureVector<byte> derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
- const MemoryRegion<byte>& salt) const;
+ template<typename Alloc, typename Alloc2>
+ secure_vector<byte> derive_key(size_t key_len,
+ const std::vector<byte, Alloc>& secret,
+ const std::vector<byte, Alloc2>& salt) const
+ {
+ return derive_key(key_len, &secret[0], secret.size(),
+ &salt[0], salt.size());
+
+ }
/**
* Derive a key
@@ -47,8 +53,8 @@ class BOTAN_DLL KDF : public Algorithm
* @param salt a diversifier
* @param salt_len size of salt in bytes
*/
- SecureVector<byte> derive_key(size_t key_len,
- const MemoryRegion<byte>& secret,
+ secure_vector<byte> derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
const byte salt[],
size_t salt_len) const;
@@ -59,7 +65,7 @@ class BOTAN_DLL KDF : public Algorithm
* @param secret_len size of secret in bytes
* @param salt a diversifier
*/
- SecureVector<byte> derive_key(size_t key_len,
+ secure_vector<byte> derive_key(size_t key_len,
const byte secret[],
size_t secret_len,
const std::string& salt = "") const;
@@ -72,7 +78,7 @@ class BOTAN_DLL KDF : public Algorithm
* @param salt a diversifier
* @param salt_len size of salt in bytes
*/
- SecureVector<byte> derive_key(size_t key_len,
+ secure_vector<byte> derive_key(size_t key_len,
const byte secret[],
size_t secret_len,
const byte salt[],
@@ -82,7 +88,7 @@ class BOTAN_DLL KDF : public Algorithm
virtual KDF* clone() const = 0;
private:
- virtual SecureVector<byte>
+ virtual secure_vector<byte>
derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte salt[], size_t salt_len) const = 0;
diff --git a/src/kdf/kdf1/kdf1.cpp b/src/kdf/kdf1/kdf1.cpp
index f3e4e208f..f00f71010 100644
--- a/src/kdf/kdf1/kdf1.cpp
+++ b/src/kdf/kdf1/kdf1.cpp
@@ -12,7 +12,7 @@ namespace Botan {
/*
* KDF1 Key Derivation Mechanism
*/
-SecureVector<byte> KDF1::derive(size_t,
+secure_vector<byte> KDF1::derive(size_t,
const byte secret[], size_t secret_len,
const byte P[], size_t P_len) const
{
diff --git a/src/kdf/kdf1/kdf1.h b/src/kdf/kdf1/kdf1.h
index f627235be..6a14d2995 100644
--- a/src/kdf/kdf1/kdf1.h
+++ b/src/kdf/kdf1/kdf1.h
@@ -19,7 +19,7 @@ namespace Botan {
class BOTAN_DLL KDF1 : public KDF
{
public:
- SecureVector<byte> derive(size_t,
+ secure_vector<byte> derive(size_t,
const byte secret[], size_t secret_len,
const byte P[], size_t P_len) const;
diff --git a/src/kdf/kdf2/kdf2.cpp b/src/kdf/kdf2/kdf2.cpp
index 51b9e41ea..39a929b58 100644
--- a/src/kdf/kdf2/kdf2.cpp
+++ b/src/kdf/kdf2/kdf2.cpp
@@ -12,11 +12,11 @@ namespace Botan {
/*
* KDF2 Key Derivation Mechanism
*/
-SecureVector<byte> KDF2::derive(size_t out_len,
+secure_vector<byte> KDF2::derive(size_t out_len,
const byte secret[], size_t secret_len,
const byte P[], size_t P_len) const
{
- SecureVector<byte> output;
+ secure_vector<byte> output;
u32bit counter = 1;
while(out_len && counter)
@@ -25,7 +25,7 @@ SecureVector<byte> KDF2::derive(size_t out_len,
hash->update_be(counter);
hash->update(P, P_len);
- SecureVector<byte> hash_result = hash->final();
+ secure_vector<byte> hash_result = hash->final();
size_t added = std::min(hash_result.size(), out_len);
output += std::make_pair(&hash_result[0], added);
diff --git a/src/kdf/kdf2/kdf2.h b/src/kdf/kdf2/kdf2.h
index e85fe6d1c..e33939df9 100644
--- a/src/kdf/kdf2/kdf2.h
+++ b/src/kdf/kdf2/kdf2.h
@@ -19,7 +19,7 @@ namespace Botan {
class BOTAN_DLL KDF2 : public KDF
{
public:
- SecureVector<byte> derive(size_t, const byte[], size_t,
+ secure_vector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "KDF2(" + hash->name() + ")"; }
diff --git a/src/kdf/mgf1/mgf1.cpp b/src/kdf/mgf1/mgf1.cpp
index 7d949c2b8..e0433a02f 100644
--- a/src/kdf/mgf1/mgf1.cpp
+++ b/src/kdf/mgf1/mgf1.cpp
@@ -25,7 +25,7 @@ void MGF1::mask(const byte in[], size_t in_len, byte out[],
{
hash->update(in, in_len);
hash->update_be(counter);
- SecureVector<byte> buffer = hash->final();
+ secure_vector<byte> buffer = hash->final();
size_t xored = std::min<size_t>(buffer.size(), out_len);
xor_buf(out, &buffer[0], xored);
diff --git a/src/kdf/prf_ssl3/prf_ssl3.cpp b/src/kdf/prf_ssl3/prf_ssl3.cpp
index 72cf023e2..8475bf40a 100644
--- a/src/kdf/prf_ssl3/prf_ssl3.cpp
+++ b/src/kdf/prf_ssl3/prf_ssl3.cpp
@@ -33,11 +33,11 @@ OctetString next_hash(size_t where, size_t want,
sha1.update(static_cast<byte>(ASCII_A_CHAR + where));
sha1.update(secret, secret_len);
sha1.update(seed, seed_len);
- SecureVector<byte> sha1_hash = sha1.final();
+ secure_vector<byte> sha1_hash = sha1.final();
md5.update(secret, secret_len);
md5.update(sha1_hash);
- SecureVector<byte> md5_hash = md5.final();
+ secure_vector<byte> md5_hash = md5.final();
return OctetString(&md5_hash[0], want);
}
@@ -47,7 +47,7 @@ OctetString next_hash(size_t where, size_t want,
/*
* SSL3 PRF
*/
-SecureVector<byte> SSL3_PRF::derive(size_t key_len,
+secure_vector<byte> SSL3_PRF::derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const
{
diff --git a/src/kdf/prf_ssl3/prf_ssl3.h b/src/kdf/prf_ssl3/prf_ssl3.h
index b07454be2..bae8badb8 100644
--- a/src/kdf/prf_ssl3/prf_ssl3.h
+++ b/src/kdf/prf_ssl3/prf_ssl3.h
@@ -18,7 +18,7 @@ namespace Botan {
class BOTAN_DLL SSL3_PRF : public KDF
{
public:
- SecureVector<byte> derive(size_t, const byte[], size_t,
+ secure_vector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "SSL3-PRF"; }
diff --git a/src/kdf/prf_tls/info.txt b/src/kdf/prf_tls/info.txt
index 9531a6a83..113c92251 100644
--- a/src/kdf/prf_tls/info.txt
+++ b/src/kdf/prf_tls/info.txt
@@ -1,4 +1,5 @@
define TLS_V10_PRF
+define TLS_V12_PRF
<requires>
hmac
diff --git a/src/kdf/prf_tls/prf_tls.cpp b/src/kdf/prf_tls/prf_tls.cpp
index 2b57cdd25..006b418c9 100644
--- a/src/kdf/prf_tls/prf_tls.cpp
+++ b/src/kdf/prf_tls/prf_tls.cpp
@@ -18,14 +18,23 @@ namespace {
/*
* TLS PRF P_hash function
*/
-void P_hash(MemoryRegion<byte>& output,
+void P_hash(secure_vector<byte>& output,
MessageAuthenticationCode* mac,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len)
{
- mac->set_key(secret, secret_len);
+ try
+ {
+ mac->set_key(secret, secret_len);
+ }
+ catch(Invalid_Key_Length)
+ {
+ throw Internal_Error("The premaster secret of " +
+ std::to_string(secret_len) +
+ " bytes is too long for the PRF");
+ }
- SecureVector<byte> A(seed, seed_len);
+ secure_vector<byte> A(seed, seed + seed_len);
size_t offset = 0;
@@ -38,7 +47,7 @@ void P_hash(MemoryRegion<byte>& output,
mac->update(A);
mac->update(seed, seed_len);
- SecureVector<byte> block = mac->final();
+ secure_vector<byte> block = mac->final();
xor_buf(&output[offset], &block[0], this_block_len);
offset += this_block_len;
@@ -65,11 +74,11 @@ TLS_PRF::~TLS_PRF()
/*
* TLS PRF
*/
-SecureVector<byte> TLS_PRF::derive(size_t key_len,
+secure_vector<byte> TLS_PRF::derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const
{
- SecureVector<byte> output(key_len);
+ secure_vector<byte> output(key_len);
size_t S1_len = (secret_len + 1) / 2,
S2_len = (secret_len + 1) / 2;
@@ -94,11 +103,11 @@ TLS_12_PRF::~TLS_12_PRF()
delete hmac;
}
-SecureVector<byte> TLS_12_PRF::derive(size_t key_len,
+secure_vector<byte> TLS_12_PRF::derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const
{
- SecureVector<byte> output(key_len);
+ secure_vector<byte> output(key_len);
P_hash(output, hmac, secret, secret_len, seed, seed_len);
diff --git a/src/kdf/prf_tls/prf_tls.h b/src/kdf/prf_tls/prf_tls.h
index 5237f17c0..fce11eae0 100644
--- a/src/kdf/prf_tls/prf_tls.h
+++ b/src/kdf/prf_tls/prf_tls.h
@@ -20,7 +20,7 @@ namespace Botan {
class BOTAN_DLL TLS_PRF : public KDF
{
public:
- SecureVector<byte> derive(size_t key_len,
+ secure_vector<byte> derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const;
@@ -40,7 +40,7 @@ class BOTAN_DLL TLS_PRF : public KDF
class BOTAN_DLL TLS_12_PRF : public KDF
{
public:
- SecureVector<byte> derive(size_t key_len,
+ secure_vector<byte> derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const;
diff --git a/src/kdf/prf_x942/prf_x942.cpp b/src/kdf/prf_x942/prf_x942.cpp
index fc31effe4..149be163f 100644
--- a/src/kdf/prf_x942/prf_x942.cpp
+++ b/src/kdf/prf_x942/prf_x942.cpp
@@ -20,11 +20,11 @@ namespace {
/*
* Encode an integer as an OCTET STRING
*/
-MemoryVector<byte> encode_x942_int(u32bit n)
+std::vector<byte> encode_x942_int(u32bit n)
{
byte n_buf[4] = { 0 };
store_be(n, n_buf);
- return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents();
+ return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents_unlocked();
}
}
@@ -32,14 +32,14 @@ MemoryVector<byte> encode_x942_int(u32bit n)
/*
* X9.42 PRF
*/
-SecureVector<byte> X942_PRF::derive(size_t key_len,
+secure_vector<byte> X942_PRF::derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte salt[], size_t salt_len) const
{
SHA_160 hash;
const OID kek_algo(key_wrap_oid);
- SecureVector<byte> key;
+ secure_vector<byte> key;
u32bit counter = 1;
while(key.size() != key_len && counter)
@@ -68,7 +68,7 @@ SecureVector<byte> X942_PRF::derive(size_t key_len,
.end_cons().get_contents()
);
- SecureVector<byte> digest = hash.final();
+ secure_vector<byte> digest = hash.final();
const size_t needed = std::min(digest.size(), key_len - key.size());
key += std::make_pair(&digest[0], needed);
diff --git a/src/kdf/prf_x942/prf_x942.h b/src/kdf/prf_x942/prf_x942.h
index e6093eda6..f86b1bdd5 100644
--- a/src/kdf/prf_x942/prf_x942.h
+++ b/src/kdf/prf_x942/prf_x942.h
@@ -18,7 +18,7 @@ namespace Botan {
class BOTAN_DLL X942_PRF : public KDF
{
public:
- SecureVector<byte> derive(size_t, const byte[], size_t,
+ secure_vector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "X942_PRF(" + key_wrap_oid + ")"; }
diff --git a/src/libstate/get_enc.cpp b/src/libstate/get_enc.cpp
index 6a87268e8..00297464b 100644
--- a/src/libstate/get_enc.cpp
+++ b/src/libstate/get_enc.cpp
@@ -96,7 +96,11 @@ EMSA* get_emsa(const std::string& algo_spec)
#if defined(BOTAN_HAS_EMSA1)
if(request.algo_name() == "EMSA1" && request.arg_count() == 1)
+ {
+ if(request.arg(0) == "Raw")
+ return new EMSA_Raw;
return new EMSA1(af.make_hash_function(request.arg(0)));
+ }
#endif
#if defined(BOTAN_HAS_EMSA1_BSI)
@@ -147,7 +151,7 @@ EME* get_eme(const std::string& algo_spec)
Algorithm_Factory& af = global_state().algorithm_factory();
if(request.algo_name() == "Raw")
- return 0; // No padding
+ return nullptr; // No padding
#if defined(BOTAN_HAS_EME_PKCS1v15)
if(request.algo_name() == "PKCS1v15" && request.arg_count() == 0)
@@ -178,7 +182,7 @@ KDF* get_kdf(const std::string& algo_spec)
Algorithm_Factory& af = global_state().algorithm_factory();
if(request.algo_name() == "Raw")
- return 0; // No KDF
+ return nullptr; // No KDF
#if defined(BOTAN_HAS_KDF1)
if(request.algo_name() == "KDF1" && request.arg_count() == 1)
@@ -195,14 +199,24 @@ KDF* get_kdf(const std::string& algo_spec)
return new X942_PRF(request.arg(0)); // OID
#endif
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0)
+ return new SSL3_PRF;
+#endif
+
#if defined(BOTAN_HAS_TLS_V10_PRF)
if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0)
return new TLS_PRF;
#endif
-#if defined(BOTAN_HAS_SSL_V3_PRF)
- if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0)
- return new SSL3_PRF;
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0)
+ return new TLS_PRF;
+#endif
+
+#if defined(BOTAN_HAS_TLS_V12_PRF)
+ if(request.algo_name() == "TLS-12-PRF" && request.arg_count() == 1)
+ return new TLS_12_PRF(af.make_mac("HMAC(" + request.arg(0) + ")"));
#endif
throw Algorithm_Not_Found(algo_spec);
diff --git a/src/libstate/global_rng.cpp b/src/libstate/global_rng.cpp
index e9ea530ac..65da38f5f 100644
--- a/src/libstate/global_rng.cpp
+++ b/src/libstate/global_rng.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/libstate.h>
-#include <botan/internal/mutex.h>
#if defined(BOTAN_HAS_RANDPOOL)
#include <botan/randpool.h>
@@ -24,6 +23,10 @@
#include <botan/internal/hres_timer.h>
#endif
+#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
+ #include <botan/internal/rdrand.h>
+#endif
+
#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
#include <botan/internal/dev_random.h>
#endif
@@ -65,6 +68,10 @@ void add_entropy_sources(RandomNumberGenerator* rng)
rng->add_entropy_source(new High_Resolution_Timestamp);
#endif
+#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
+ rng->add_entropy_source(new Intel_Rdrand);
+#endif
+
#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
rng->add_entropy_source(
new Device_EntropySource(
@@ -107,62 +114,62 @@ class Serialized_PRNG : public RandomNumberGenerator
public:
void randomize(byte out[], size_t len)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
rng->randomize(out, len);
}
bool is_seeded() const
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
return rng->is_seeded();
}
void clear()
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
rng->clear();
}
std::string name() const
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
return rng->name();
}
void reseed(size_t poll_bits)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
rng->reseed(poll_bits);
}
void add_entropy_source(EntropySource* es)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
rng->add_entropy_source(es);
}
void add_entropy(const byte in[], size_t len)
{
- Mutex_Holder lock(mutex);
+ std::lock_guard<std::mutex> lock(mutex);
rng->add_entropy(in, len);
}
// We do not own the mutex; Library_State does
- Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) :
+ Serialized_PRNG(RandomNumberGenerator* r, std::mutex& m) :
mutex(m), rng(r) {}
~Serialized_PRNG() { delete rng; }
private:
- Mutex* mutex;
+ std::mutex& mutex;
RandomNumberGenerator* rng;
};
}
RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af,
- Mutex* mutex)
+ std::mutex& mutex)
{
- RandomNumberGenerator* rng = 0;
+ RandomNumberGenerator* rng = nullptr;
#if defined(BOTAN_HAS_HMAC_RNG)
diff --git a/src/libstate/global_state.cpp b/src/libstate/global_state.cpp
index 43c935ca3..6a846d9b0 100644
--- a/src/libstate/global_state.cpp
+++ b/src/libstate/global_state.cpp
@@ -22,7 +22,7 @@ namespace Global_State_Management {
*/
namespace {
-Library_State* global_lib_state = 0;
+Library_State* global_lib_state = nullptr;
}
@@ -37,7 +37,7 @@ Library_State& global_state()
if(!global_lib_state)
{
global_lib_state = new Library_State;
- global_lib_state->initialize(true);
+ global_lib_state->initialize();
}
return (*global_lib_state);
@@ -83,7 +83,7 @@ Library_State* swap_global_state(Library_State* new_state)
*/
bool global_state_exists()
{
- return (global_lib_state != 0);
+ return (global_lib_state != nullptr);
}
}
diff --git a/src/libstate/info.txt b/src/libstate/info.txt
index d48ad70d5..0e523e601 100644
--- a/src/libstate/info.txt
+++ b/src/libstate/info.txt
@@ -38,8 +38,6 @@ hmac_rng
kdf
mac
mode_pad
-mutex
-noop_mutex
pbkdf
pk_pad
pubkey
@@ -47,5 +45,4 @@ rng
sha2_32
sha2_64
stream
-system_alloc
</requires>
diff --git a/src/libstate/init.cpp b/src/libstate/init.cpp
index 7cdc615bd..2d724f366 100644
--- a/src/libstate/init.cpp
+++ b/src/libstate/init.cpp
@@ -1,12 +1,11 @@
/*
* Default Initialization Function
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/init.h>
-#include <botan/parsing.h>
#include <botan/libstate.h>
#include <botan/global_state.h>
@@ -15,48 +14,20 @@ namespace Botan {
/*
* Library Initialization
*/
-void LibraryInitializer::initialize(const std::string& arg_string)
+void LibraryInitializer::initialize(const std::string&)
{
- bool thread_safe = false;
-
- const std::vector<std::string> arg_list = split_on(arg_string, ' ');
- for(size_t i = 0; i != arg_list.size(); ++i)
- {
- if(arg_list[i].size() == 0)
- continue;
-
- std::string name, value;
-
- if(arg_list[i].find('=') == std::string::npos)
- {
- name = arg_list[i];
- value = "true";
- }
- else
- {
- std::vector<std::string> name_and_value = split_on(arg_list[i], '=');
- name = name_and_value[0];
- value = name_and_value[1];
- }
-
- bool is_on =
- (value == "1" || value == "true" || value == "yes" || value == "on");
-
- if(name == "thread_safe")
- thread_safe = is_on;
- }
try
{
/*
This two stage initialization process is because Library_State's
constructor will implicitly refer to global state through the
- allocators and so for, so global_state() has to be a valid
+ allocators and so forth, so global_state() has to be a valid
reference before initialize() can be called. Yeah, gross.
*/
Global_State_Management::set_global_state(new Library_State);
- global_state().initialize(thread_safe);
+ global_state().initialize();
}
catch(...)
{
@@ -70,7 +41,7 @@ void LibraryInitializer::initialize(const std::string& arg_string)
*/
void LibraryInitializer::deinitialize()
{
- Global_State_Management::set_global_state(0);
+ Global_State_Management::set_global_state(nullptr);
}
}
diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp
index 076b55fcf..78ff9135c 100644
--- a/src/libstate/libstate.cpp
+++ b/src/libstate/libstate.cpp
@@ -9,30 +9,14 @@
#include <botan/charset.h>
#include <botan/engine.h>
#include <botan/cpuid.h>
-#include <botan/internal/defalloc.h>
#include <botan/internal/core_engine.h>
-#include <botan/internal/mutex.h>
-#include <botan/internal/mux_noop.h>
#include <botan/internal/stl_util.h>
-#include <botan/internal/mlock.h>
#include <algorithm>
#if defined(BOTAN_HAS_SELFTESTS)
#include <botan/selftest.h>
#endif
-#if defined(BOTAN_HAS_MUTEX_PTHREAD)
- #include <botan/internal/mux_pthr.h>
-#elif defined(BOTAN_HAS_MUTEX_WIN32)
- #include <botan/internal/mux_win32.h>
-#elif defined(BOTAN_HAS_MUTEX_QT)
- #include <botan/internal/mux_qt.h>
-#endif
-
-#if defined(BOTAN_HAS_ALLOC_MMAP)
- #include <botan/internal/mmap_mem.h>
-#endif
-
#if defined(BOTAN_HAS_ENGINE_ASSEMBLER)
#include <botan/internal/asm_engine.h>
#endif
@@ -56,67 +40,12 @@
namespace Botan {
/*
-* Get a new mutex object
-*/
-Mutex* Library_State::get_mutex() const
- {
- return mutex_factory->make();
- }
-
-/*
-* Get an allocator by its name
-*/
-Allocator* Library_State::get_allocator(const std::string& type) const
- {
- Mutex_Holder lock(allocator_lock);
-
- if(type != "")
- return search_map<std::string, Allocator*>(alloc_factory, type, 0);
-
- if(!cached_default_allocator)
- {
- cached_default_allocator =
- search_map<std::string, Allocator*>(alloc_factory,
- default_allocator_name, 0);
- }
-
- return cached_default_allocator;
- }
-
-/*
-* Create a new name to object mapping
-*/
-void Library_State::add_allocator(Allocator* allocator)
- {
- Mutex_Holder lock(allocator_lock);
-
- allocator->init();
-
- allocators.push_back(allocator);
- alloc_factory[allocator->type()] = allocator;
- }
-
-/*
-* Set the default allocator type
-*/
-void Library_State::set_default_allocator(const std::string& type)
- {
- Mutex_Holder lock(allocator_lock);
-
- if(type == "")
- return;
-
- default_allocator_name = type;
- cached_default_allocator = 0;
- }
-
-/*
* Get a configuration value
*/
std::string Library_State::get(const std::string& section,
- const std::string& key) const
+ const std::string& key)
{
- Mutex_Holder lock(config_lock);
+ std::lock_guard<std::mutex> lock(config_lock);
return search_map<std::string, std::string>(config,
section + "/" + key, "");
@@ -126,9 +55,9 @@ std::string Library_State::get(const std::string& section,
* See if a particular option has been set
*/
bool Library_State::is_set(const std::string& section,
- const std::string& key) const
+ const std::string& key)
{
- Mutex_Holder lock(config_lock);
+ std::lock_guard<std::mutex> lock(config_lock);
return config.count(section + "/" + key) != 0;
}
@@ -139,12 +68,11 @@ bool Library_State::is_set(const std::string& section,
void Library_State::set(const std::string& section, const std::string& key,
const std::string& value, bool overwrite)
{
- Mutex_Holder lock(config_lock);
+ std::lock_guard<std::mutex> lock(config_lock);
std::string full_key = section + "/" + key;
- std::map<std::string, std::string>::const_iterator i =
- config.find(full_key);
+ auto i = config.find(full_key);
if(overwrite || i == config.end() || i->second == "")
config[full_key] = value;
@@ -161,7 +89,7 @@ void Library_State::add_alias(const std::string& key, const std::string& value)
/*
* Dereference an alias to a fixed name
*/
-std::string Library_State::deref_alias(const std::string& key) const
+std::string Library_State::deref_alias(const std::string& key)
{
std::string result = key;
while(is_set("alias", result))
@@ -184,7 +112,7 @@ Algorithm_Factory& Library_State::algorithm_factory() const
*/
RandomNumberGenerator& Library_State::global_rng()
{
- Mutex_Holder lock(global_rng_lock);
+ std::lock_guard<std::mutex> lock(global_rng_lock);
if(!global_rng_ptr)
global_rng_ptr = make_global_rng(algorithm_factory(),
@@ -196,46 +124,16 @@ RandomNumberGenerator& Library_State::global_rng()
/*
* Load a set of modules
*/
-void Library_State::initialize(bool thread_safe)
+void Library_State::initialize()
{
CPUID::initialize();
- if(mutex_factory)
+ if(m_algorithm_factory)
throw Invalid_State("Library_State has already been initialized");
- if(!thread_safe)
- {
- mutex_factory = new Noop_Mutex_Factory;
- }
- else
- {
-#if defined(BOTAN_HAS_MUTEX_PTHREAD)
- mutex_factory = new Pthread_Mutex_Factory;
-#elif defined(BOTAN_HAS_MUTEX_WIN32)
- mutex_factory = new Win32_Mutex_Factory;
-#elif defined(BOTAN_HAS_MUTEX_QT)
- mutex_factory Qt_Mutex_Factory;
-#else
- throw Invalid_State("Could not find a thread-safe mutex object to use");
-#endif
- }
-
- allocator_lock = get_mutex();
- config_lock = get_mutex();
- global_rng_lock = get_mutex();
-
- default_allocator_name = has_mlock() ? "locking" : "malloc";
-
- add_allocator(new Malloc_Allocator);
- add_allocator(new Locking_Allocator(get_mutex()));
-
-#if defined(BOTAN_HAS_ALLOC_MMAP)
- add_allocator(new MemoryMapping_Allocator(get_mutex()));
-#endif
-
load_default_config();
- m_algorithm_factory = new Algorithm_Factory(*mutex_factory);
+ m_algorithm_factory = new Algorithm_Factory();
#if defined(BOTAN_HAS_ENGINE_GNU_MP)
algorithm_factory().add_engine(new GMP_Engine);
@@ -269,13 +167,9 @@ void Library_State::initialize(bool thread_safe)
*/
Library_State::Library_State()
{
- mutex_factory = 0;
- allocator_lock = config_lock = 0;
- cached_default_allocator = 0;
- m_algorithm_factory = 0;
+ m_algorithm_factory = nullptr;
- global_rng_lock = 0;
- global_rng_ptr = 0;
+ global_rng_ptr = nullptr;
}
/*
@@ -284,20 +178,10 @@ Library_State::Library_State()
Library_State::~Library_State()
{
delete m_algorithm_factory;
- delete global_rng_ptr;
-
- cached_default_allocator = 0;
+ m_algorithm_factory = nullptr;
- for(size_t i = 0; i != allocators.size(); ++i)
- {
- allocators[i]->destroy();
- delete allocators[i];
- }
-
- delete global_rng_lock;
- delete allocator_lock;
- delete mutex_factory;
- delete config_lock;
+ delete global_rng_ptr;
+ global_rng_ptr = nullptr;
}
}
diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h
index aa957c8c9..b260a5bb9 100644
--- a/src/libstate/libstate.h
+++ b/src/libstate/libstate.h
@@ -9,20 +9,18 @@
#define BOTAN_LIB_STATE_H__
#include <botan/global_state.h>
-#include <botan/allocate.h>
#include <botan/algo_factory.h>
#include <botan/rng.h>
+#include <mutex>
#include <string>
#include <vector>
#include <map>
namespace Botan {
-class Mutex;
-
-/**
-* Global state container aka the buritto at the center of it all
+/*
+* Global State Container Base
*/
class BOTAN_DLL Library_State
{
@@ -30,10 +28,10 @@ class BOTAN_DLL Library_State
Library_State();
~Library_State();
- /**
- * @param thread_safe should a mutex be used for serialization
- */
- void initialize(bool thread_safe);
+ Library_State(const Library_State&) = delete;
+ Library_State& operator=(const Library_State&) = delete;
+
+ void initialize();
/**
* @return global Algorithm_Factory
@@ -46,18 +44,6 @@ class BOTAN_DLL Library_State
RandomNumberGenerator& global_rng();
/**
- * @param name the name of the allocator
- * @return allocator matching this name, or NULL
- */
- Allocator* get_allocator(const std::string& name = "") const;
-
- /**
- * Add a new allocator to the list of available ones
- * @param alloc the allocator to add
- */
- void add_allocator(Allocator* alloc);
-
- /**
* Set the default allocator
* @param name the name of the allocator to use as the default
*/
@@ -70,7 +56,7 @@ class BOTAN_DLL Library_State
* @result the value of the parameter
*/
std::string get(const std::string& section,
- const std::string& key) const;
+ const std::string& key);
/**
* Check whether a certain parameter is set or not.
@@ -80,7 +66,7 @@ class BOTAN_DLL Library_State
* false otherwise
*/
bool is_set(const std::string& section,
- const std::string& key) const;
+ const std::string& key);
/**
* Set a configuration parameter.
@@ -109,35 +95,19 @@ class BOTAN_DLL Library_State
* @param alias the alias to resolve.
* @return what the alias stands for
*/
- std::string deref_alias(const std::string& alias) const;
-
- /**
- * @return newly created Mutex (free with delete)
- */
- Mutex* get_mutex() const;
+ std::string deref_alias(const std::string&);
private:
static RandomNumberGenerator* make_global_rng(Algorithm_Factory& af,
- Mutex* mutex);
+ std::mutex& mutex);
void load_default_config();
- Library_State(const Library_State&) {}
- Library_State& operator=(const Library_State&) { return (*this); }
-
- class Mutex_Factory* mutex_factory;
-
- Mutex* global_rng_lock;
+ std::mutex global_rng_lock;
RandomNumberGenerator* global_rng_ptr;
- Mutex* config_lock;
+ std::mutex config_lock;
std::map<std::string, std::string> config;
- Mutex* allocator_lock;
- std::string default_allocator_name;
- std::map<std::string, Allocator*> alloc_factory;
- mutable Allocator* cached_default_allocator;
- std::vector<Allocator*> allocators;
-
Algorithm_Factory* m_algorithm_factory;
};
diff --git a/src/libstate/lookup.h b/src/libstate/lookup.h
index e10c195b8..96364e1d9 100644
--- a/src/libstate/lookup.h
+++ b/src/libstate/lookup.h
@@ -235,7 +235,7 @@ BOTAN_DLL bool have_algorithm(const std::string& algo_spec);
inline bool have_block_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_block_cipher(algo_spec) != 0);
+ return (af.prototype_block_cipher(algo_spec) != nullptr);
}
/**
@@ -248,7 +248,7 @@ inline bool have_block_cipher(const std::string& algo_spec)
inline bool have_stream_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_stream_cipher(algo_spec) != 0);
+ return (af.prototype_stream_cipher(algo_spec) != nullptr);
}
/**
@@ -261,7 +261,7 @@ inline bool have_stream_cipher(const std::string& algo_spec)
inline bool have_hash(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_hash_function(algo_spec) != 0);
+ return (af.prototype_hash_function(algo_spec) != nullptr);
}
/**
@@ -274,7 +274,7 @@ inline bool have_hash(const std::string& algo_spec)
inline bool have_mac(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_mac(algo_spec) != 0);
+ return (af.prototype_mac(algo_spec) != nullptr);
}
/*
diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp
index 7abea7d4d..b1da22ce8 100644
--- a/src/libstate/policy.cpp
+++ b/src/libstate/policy.cpp
@@ -337,6 +337,15 @@ void set_default_dl_groups(Library_State& config)
"NgRlEbmT//////////8="
"-----END X942 DH PARAMETERS-----");
+ config.set("dl", "modp/srp/1536",
+ "-----BEGIN DH PARAMETERS-----"
+ "MIHHAoHBAJ3vPK+5OSd6sfEqhheke7vbpR30maxMgL7uqWFLGcxNX09fVW4ny95R"
+ "xqlL5GB6KRVYkDug0PhDgLZVu5oi6NzfAop87Gfw0IE0sci5eYkUm2CeC+O6tj1H"
+ "VIOB28Wx/HZOP0tT3Z2hFYv9PiucjPVu3wGVOTSWJ9sv1T0kt8SGZXcuQ31sf4zk"
+ "QnNK98y3roN8Jkrjqb64f4ov6bi1KS5aAh//XpFHnoznoowkQsbzFRgPk0maI03P"
+ "duP+0TX5uwIBAg=="
+ "-----END DH PARAMETERS-----");
+
config.set("dl", "modp/ietf/2048",
"-----BEGIN X942 DH PARAMETERS-----"
"MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
@@ -388,6 +397,19 @@ void set_default_dl_groups(Library_State& config)
"JcFokFSdaWV//////////w=="
"-----END X942 DH PARAMETERS-----");
+ config.set("dl", "modp/srp/3072",
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
+ "yv//////////AgEF"
+ "-----END DH PARAMETERS-----");
+
config.set("dl", "modp/ietf/4096",
"-----BEGIN X942 DH PARAMETERS-----"
"MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
@@ -414,6 +436,21 @@ void set_default_dl_groups(Library_State& config)
"ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8="
"-----END X942 DH PARAMETERS-----");
+ config.set("dl", "modp/srp/4096",
+ "-----BEGIN DH PARAMETERS-----"
+ "MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQU="
+ "-----END DH PARAMETERS-----");
+
config.set("dl", "modp/ietf/6144",
"-----BEGIN X942 DH PARAMETERS-----"
"MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
@@ -451,6 +488,27 @@ void set_default_dl_groups(Library_State& config)
"jzbmIBJ//////////wIBAg=="
"-----END X942 DH PARAMETERS-----");
+ config.set("dl", "modp/srp/6144",
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
+ "JP//////////AgEF"
+ "-----END DH PARAMETERS-----");
+
config.set("dl", "modp/ietf/8192",
"-----BEGIN X942 DH PARAMETERS-----"
"MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
@@ -498,6 +556,32 @@ void set_default_dl_groups(Library_State& config)
"034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC"
"-----END X942 DH PARAMETERS-----");
+ config.set("dl", "modp/srp/8192",
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
+ "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
+ "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
+ "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
+ "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
+ "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
+ "38gfVuiAuW5xYMmA3Zjt09///////////wIBEw=="
+ "-----END DH PARAMETERS-----");
+
config.set("dl", "dsa/jce/512",
"-----BEGIN DSA PARAMETERS-----"
"MIGdAkEA/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQT"
diff --git a/src/mac/cbc_mac/cbc_mac.h b/src/mac/cbc_mac/cbc_mac.h
index 5cc8adc67..be25718d9 100644
--- a/src/mac/cbc_mac/cbc_mac.h
+++ b/src/mac/cbc_mac/cbc_mac.h
@@ -40,7 +40,7 @@ class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode
void key_schedule(const byte[], size_t);
BlockCipher* e;
- SecureVector<byte> state;
+ secure_vector<byte> state;
size_t position;
};
diff --git a/src/mac/cmac/cmac.cpp b/src/mac/cmac/cmac.cpp
index baf22f4e8..00120cf14 100644
--- a/src/mac/cmac/cmac.cpp
+++ b/src/mac/cmac/cmac.cpp
@@ -13,12 +13,12 @@ namespace Botan {
/*
* Perform CMAC's multiplication in GF(2^n)
*/
-SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in,
+secure_vector<byte> CMAC::poly_double(const secure_vector<byte>& in,
byte polynomial)
{
const byte poly_xor = (in[0] & 0x80) ? polynomial : 0;
- SecureVector<byte> out = in;
+ secure_vector<byte> out = in;
byte carry = 0;
for(size_t i = out.size(); i != 0; --i)
@@ -38,7 +38,7 @@ SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in,
*/
void CMAC::add_data(const byte input[], size_t length)
{
- buffer.copy(position, input, length);
+ buffer_insert(buffer, position, input, length);
if(position + length > output_length())
{
xor_buf(state, buffer, output_length());
@@ -52,7 +52,7 @@ void CMAC::add_data(const byte input[], size_t length)
input += output_length();
length -= output_length();
}
- buffer.copy(input, length);
+ copy_mem(&buffer[0], input, length);
position = 0;
}
position += length;
diff --git a/src/mac/cmac/cmac.h b/src/mac/cmac/cmac.h
index 98634bdb7..b398f2563 100644
--- a/src/mac/cmac/cmac.h
+++ b/src/mac/cmac/cmac.h
@@ -35,8 +35,8 @@ class BOTAN_DLL CMAC : public MessageAuthenticationCode
* @param in the input
* @param polynomial the byte value of the polynomial
*/
- static SecureVector<byte> poly_double(const MemoryRegion<byte>& in,
- byte polynomial);
+ static secure_vector<byte> poly_double(const secure_vector<byte>& in,
+ byte polynomial);
/**
* @param cipher the underlying block cipher to use
@@ -49,7 +49,7 @@ class BOTAN_DLL CMAC : public MessageAuthenticationCode
void key_schedule(const byte[], size_t);
BlockCipher* e;
- SecureVector<byte> buffer, state, B, P;
+ secure_vector<byte> buffer, state, B, P;
size_t position;
byte polynomial;
};
diff --git a/src/mac/hmac/hmac.cpp b/src/mac/hmac/hmac.cpp
index fc35e26ea..4b4ed2f70 100644
--- a/src/mac/hmac/hmac.cpp
+++ b/src/mac/hmac/hmac.cpp
@@ -37,12 +37,16 @@ void HMAC::final_result(byte mac[])
void HMAC::key_schedule(const byte key[], size_t length)
{
hash->clear();
+
+ i_key.resize(hash->hash_block_size());
+ o_key.resize(hash->hash_block_size());
+
std::fill(i_key.begin(), i_key.end(), 0x36);
std::fill(o_key.begin(), o_key.end(), 0x5C);
if(length > hash->hash_block_size())
{
- SecureVector<byte> hmac_key = hash->process(key, length);
+ secure_vector<byte> hmac_key = hash->process(key, length);
xor_buf(i_key, hmac_key, hmac_key.size());
xor_buf(o_key, hmac_key, hmac_key.size());
}
@@ -61,8 +65,8 @@ void HMAC::key_schedule(const byte key[], size_t length)
void HMAC::clear()
{
hash->clear();
- zeroise(i_key);
- zeroise(o_key);
+ i_key.clear();
+ o_key.clear();
}
/*
@@ -88,9 +92,6 @@ HMAC::HMAC(HashFunction* hash_in) : hash(hash_in)
{
if(hash->hash_block_size() == 0)
throw Invalid_Argument("HMAC cannot be used with " + hash->name());
-
- i_key.resize(hash->hash_block_size());
- o_key.resize(hash->hash_block_size());
}
}
diff --git a/src/mac/hmac/hmac.h b/src/mac/hmac/hmac.h
index b76a058f4..cb5bd6917 100644
--- a/src/mac/hmac/hmac.h
+++ b/src/mac/hmac/hmac.h
@@ -27,7 +27,7 @@ class BOTAN_DLL HMAC : public MessageAuthenticationCode
Key_Length_Specification key_spec() const
{
- return Key_Length_Specification(0, 2*hash->hash_block_size());
+ return Key_Length_Specification(0, 512);
}
/**
@@ -41,7 +41,7 @@ class BOTAN_DLL HMAC : public MessageAuthenticationCode
void key_schedule(const byte[], size_t);
HashFunction* hash;
- SecureVector<byte> i_key, o_key;
+ secure_vector<byte> i_key, o_key;
};
}
diff --git a/src/mac/mac.cpp b/src/mac/mac.cpp
index 2ef4ab64c..094aa1b4a 100644
--- a/src/mac/mac.cpp
+++ b/src/mac/mac.cpp
@@ -15,7 +15,7 @@ namespace Botan {
*/
bool MessageAuthenticationCode::verify_mac(const byte mac[], size_t length)
{
- SecureVector<byte> our_mac = final();
+ secure_vector<byte> our_mac = final();
if(our_mac.size() != length)
return false;
diff --git a/src/mac/ssl3mac/ssl3_mac.cpp b/src/mac/ssl3mac/ssl3_mac.cpp
index a07622eb3..8979d1291 100644
--- a/src/mac/ssl3mac/ssl3_mac.cpp
+++ b/src/mac/ssl3mac/ssl3_mac.cpp
@@ -35,11 +35,20 @@ void SSL3_MAC::final_result(byte mac[])
void SSL3_MAC::key_schedule(const byte key[], size_t length)
{
hash->clear();
+
+ // Quirk to deal with specification bug
+ const size_t inner_hash_length =
+ (hash->name() == "SHA-160") ? 60 : hash->hash_block_size();
+
+ i_key.resize(inner_hash_length);
+ o_key.resize(inner_hash_length);
+
std::fill(i_key.begin(), i_key.end(), 0x36);
std::fill(o_key.begin(), o_key.end(), 0x5C);
- i_key.copy(key, length);
- o_key.copy(key, length);
+ copy_mem(&i_key[0], key, length);
+ copy_mem(&o_key[0], key, length);
+
hash->update(i_key);
}
@@ -49,8 +58,8 @@ void SSL3_MAC::key_schedule(const byte key[], size_t length)
void SSL3_MAC::clear()
{
hash->clear();
- zeroise(i_key);
- zeroise(o_key);
+ i_key.clear();
+ o_key.clear();
}
/*
@@ -76,13 +85,6 @@ SSL3_MAC::SSL3_MAC(HashFunction* hash_in) : hash(hash_in)
{
if(hash->hash_block_size() == 0)
throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
-
- // Quirk to deal with specification bug
- const size_t INNER_HASH_LENGTH =
- (hash->name() == "SHA-160") ? 60 : hash->hash_block_size();
-
- i_key.resize(INNER_HASH_LENGTH);
- o_key.resize(INNER_HASH_LENGTH);
}
}
diff --git a/src/mac/ssl3mac/ssl3_mac.h b/src/mac/ssl3mac/ssl3_mac.h
index a85a78263..d23ac023c 100644
--- a/src/mac/ssl3mac/ssl3_mac.h
+++ b/src/mac/ssl3mac/ssl3_mac.h
@@ -41,7 +41,7 @@ class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode
void key_schedule(const byte[], size_t);
HashFunction* hash;
- SecureVector<byte> i_key, o_key;
+ secure_vector<byte> i_key, o_key;
};
}
diff --git a/src/mac/x919_mac/x919_mac.cpp b/src/mac/x919_mac/x919_mac.cpp
index fcbe77537..faf6138ef 100644
--- a/src/mac/x919_mac/x919_mac.cpp
+++ b/src/mac/x919_mac/x919_mac.cpp
@@ -44,7 +44,7 @@ void ANSI_X919_MAC::final_result(byte mac[])
{
if(position)
e->encrypt(state);
- d->decrypt(state, mac);
+ d->decrypt(&state[0], mac);
e->encrypt(mac);
zeroise(state);
position = 0;
diff --git a/src/mac/x919_mac/x919_mac.h b/src/mac/x919_mac/x919_mac.h
index 58a005e0b..4b5e63b33 100644
--- a/src/mac/x919_mac/x919_mac.h
+++ b/src/mac/x919_mac/x919_mac.h
@@ -41,7 +41,7 @@ class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode
BlockCipher* e;
BlockCipher* d;
- SecureVector<byte> state;
+ secure_vector<byte> state;
size_t position;
};
diff --git a/src/math/bigint/big_code.cpp b/src/math/bigint/big_code.cpp
index 75a310a7c..a55ec662e 100644
--- a/src/math/bigint/big_code.cpp
+++ b/src/math/bigint/big_code.cpp
@@ -21,7 +21,7 @@ void BigInt::encode(byte output[], const BigInt& n, Base base)
n.binary_encode(output);
else if(base == Hexadecimal)
{
- SecureVector<byte> binary(n.encoded_size(Binary));
+ secure_vector<byte> binary(n.encoded_size(Binary));
n.binary_encode(&binary[0]);
hex_encode(reinterpret_cast<char*>(output),
@@ -61,9 +61,23 @@ void BigInt::encode(byte output[], const BigInt& n, Base base)
/*
* Encode a BigInt
*/
-SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
+std::vector<byte> BigInt::encode(const BigInt& n, Base base)
{
- SecureVector<byte> output(n.encoded_size(base));
+ std::vector<byte> output(n.encoded_size(base));
+ encode(&output[0], n, base);
+ if(base != Binary)
+ for(size_t j = 0; j != output.size(); ++j)
+ if(output[j] == 0)
+ output[j] = '0';
+ return output;
+ }
+
+/*
+* Encode a BigInt
+*/
+secure_vector<byte> BigInt::encode_locked(const BigInt& n, Base base)
+ {
+ secure_vector<byte> output(n.encoded_size(base));
encode(&output[0], n, base);
if(base != Binary)
for(size_t j = 0; j != output.size(); ++j)
@@ -75,7 +89,7 @@ SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
/*
* Encode a BigInt, with leading 0s if needed
*/
-SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes)
+secure_vector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes)
{
const size_t n_bytes = n.bytes();
if(n_bytes > bytes)
@@ -83,7 +97,7 @@ SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes)
const size_t leading_0s = bytes - n_bytes;
- SecureVector<byte> output(bytes);
+ secure_vector<byte> output(bytes);
encode(&output[leading_0s], n, Binary);
return output;
}
@@ -91,14 +105,6 @@ SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes)
/*
* Decode a BigInt
*/
-BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base)
- {
- return BigInt::decode(&buf[0], buf.size(), base);
- }
-
-/*
-* Decode a BigInt
-*/
BigInt BigInt::decode(const byte buf[], size_t length, Base base)
{
BigInt r;
@@ -106,12 +112,14 @@ BigInt BigInt::decode(const byte buf[], size_t length, Base base)
r.binary_decode(buf, length);
else if(base == Hexadecimal)
{
- SecureVector<byte> binary;
+ secure_vector<byte> binary;
if(length % 2)
{
// Handle lack of leading 0
- const char buf0_with_leading_0[2] = { '0', buf[0] };
+ const char buf0_with_leading_0[2] =
+ { '0', static_cast<char>(buf[0]) };
+
binary = hex_decode(buf0_with_leading_0, 2);
binary += hex_decode(reinterpret_cast<const char*>(&buf[1]),
diff --git a/src/math/bigint/big_io.cpp b/src/math/bigint/big_io.cpp
index 70e4a464a..130a98a3b 100644
--- a/src/math/bigint/big_io.cpp
+++ b/src/math/bigint/big_io.cpp
@@ -27,7 +27,7 @@ std::ostream& operator<<(std::ostream& stream, const BigInt& n)
{
if(n < 0)
stream.write("-", 1);
- SecureVector<byte> buffer = BigInt::encode(n, base);
+ const std::vector<byte> buffer = BigInt::encode(n, base);
size_t skip = 0;
while(buffer[skip] == '0' && skip < buffer.size())
++skip;
diff --git a/src/math/bigint/big_ops2.cpp b/src/math/bigint/big_ops2.cpp
index ff5cc7922..ea2bdc961 100644
--- a/src/math/bigint/big_ops2.cpp
+++ b/src/math/bigint/big_ops2.cpp
@@ -23,15 +23,15 @@ BigInt& BigInt::operator+=(const BigInt& y)
grow_to(reg_size);
if(sign() == y.sign())
- bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ bigint_add2(data(), reg_size - 1, y.data(), y_sw);
else
{
s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
if(relative_size < 0)
{
- SecureVector<word> z(reg_size - 1);
- bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
+ secure_vector<word> z(reg_size - 1);
+ bigint_sub3(&z[0], y.data(), reg_size - 1, data(), x_sw);
copy_mem(&reg[0], &z[0], z.size());
set_sign(y.sign());
}
@@ -41,7 +41,7 @@ BigInt& BigInt::operator+=(const BigInt& y)
set_sign(Positive);
}
else if(relative_size > 0)
- bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ bigint_sub2(data(), x_sw, y.data(), y_sw);
}
return (*this);
@@ -62,9 +62,9 @@ BigInt& BigInt::operator-=(const BigInt& y)
if(relative_size < 0)
{
if(sign() == y.sign())
- bigint_sub2_rev(get_reg(), y.data(), y_sw);
+ bigint_sub2_rev(data(), y.data(), y_sw);
else
- bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ bigint_add2(data(), reg_size - 1, y.data(), y_sw);
set_sign(y.reverse_sign());
}
@@ -76,14 +76,14 @@ BigInt& BigInt::operator-=(const BigInt& y)
set_sign(Positive);
}
else
- bigint_shl1(get_reg(), x_sw, 0, 1);
+ bigint_shl1(data(), x_sw, 0, 1);
}
else if(relative_size > 0)
{
if(sign() == y.sign())
- bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ bigint_sub2(data(), x_sw, y.data(), y_sw);
else
- bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ bigint_add2(data(), reg_size - 1, y.data(), y_sw);
}
return (*this);
@@ -105,22 +105,22 @@ BigInt& BigInt::operator*=(const BigInt& y)
else if(x_sw == 1 && y_sw)
{
grow_to(y_sw + 2);
- bigint_linmul3(get_reg(), y.data(), y_sw, word_at(0));
+ bigint_linmul3(data(), y.data(), y_sw, word_at(0));
}
else if(y_sw == 1 && x_sw)
{
grow_to(x_sw + 2);
- bigint_linmul2(get_reg(), x_sw, y.word_at(0));
+ bigint_linmul2(data(), x_sw, y.word_at(0));
}
else
{
grow_to(size() + y.size());
- SecureVector<word> z(data(), x_sw);
- SecureVector<word> workspace(size());
+ secure_vector<word> z(data(), data() + x_sw);
+ secure_vector<word> workspace(size());
- bigint_mul(get_reg(), size(), workspace,
- z, z.size(), x_sw,
+ bigint_mul(data(), size(), &workspace[0],
+ &z[0], z.size(), x_sw,
y.data(), y.size(), y_sw);
}
@@ -159,7 +159,7 @@ word BigInt::operator%=(word mod)
word result = (word_at(0) & (mod - 1));
clear();
grow_to(2);
- get_reg()[0] = result;
+ reg[0] = result;
return result;
}
@@ -171,9 +171,9 @@ word BigInt::operator%=(word mod)
grow_to(2);
if(remainder && sign() == BigInt::Negative)
- get_reg()[0] = mod - remainder;
+ reg[0] = mod - remainder;
else
- get_reg()[0] = remainder;
+ reg[0] = remainder;
set_sign(BigInt::Positive);
@@ -192,7 +192,7 @@ BigInt& BigInt::operator<<=(size_t shift)
words = sig_words();
grow_to(words + shift_words + (shift_bits ? 1 : 0));
- bigint_shl1(get_reg(), words, shift_words, shift_bits);
+ bigint_shl1(data(), words, shift_words, shift_bits);
}
return (*this);
@@ -208,7 +208,7 @@ BigInt& BigInt::operator>>=(size_t shift)
const size_t shift_words = shift / MP_WORD_BITS,
shift_bits = shift % MP_WORD_BITS;
- bigint_shr1(get_reg(), sig_words(), shift_words, shift_bits);
+ bigint_shr1(data(), sig_words(), shift_words, shift_bits);
if(is_zero())
set_sign(Positive);
diff --git a/src/math/bigint/big_ops3.cpp b/src/math/bigint/big_ops3.cpp
index 52472bc52..a33b32bb7 100644
--- a/src/math/bigint/big_ops3.cpp
+++ b/src/math/bigint/big_ops3.cpp
@@ -23,20 +23,20 @@ BigInt operator+(const BigInt& x, const BigInt& y)
BigInt z(x.sign(), std::max(x_sw, y_sw) + 1);
if((x.sign() == y.sign()))
- bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw);
else
{
s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw);
if(relative_size < 0)
{
- bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
+ bigint_sub3(z.data(), y.data(), y_sw, x.data(), x_sw);
z.set_sign(y.sign());
}
else if(relative_size == 0)
z.set_sign(BigInt::Positive);
else if(relative_size > 0)
- bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ bigint_sub3(z.data(), x.data(), x_sw, y.data(), y_sw);
}
return z;
@@ -56,22 +56,22 @@ BigInt operator-(const BigInt& x, const BigInt& y)
if(relative_size < 0)
{
if(x.sign() == y.sign())
- bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
+ bigint_sub3(z.data(), y.data(), y_sw, x.data(), x_sw);
else
- bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw);
z.set_sign(y.reverse_sign());
}
else if(relative_size == 0)
{
if(x.sign() != y.sign())
- bigint_shl2(z.get_reg(), x.data(), x_sw, 0, 1);
+ bigint_shl2(z.data(), x.data(), x_sw, 0, 1);
}
else if(relative_size > 0)
{
if(x.sign() == y.sign())
- bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ bigint_sub3(z.data(), x.data(), x_sw, y.data(), y_sw);
else
- bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw);
z.set_sign(x.sign());
}
return z;
@@ -87,13 +87,13 @@ BigInt operator*(const BigInt& x, const BigInt& y)
BigInt z(BigInt::Positive, x.size() + y.size());
if(x_sw == 1 && y_sw)
- bigint_linmul3(z.get_reg(), y.data(), y_sw, x.word_at(0));
+ bigint_linmul3(z.data(), y.data(), y_sw, x.word_at(0));
else if(y_sw == 1 && x_sw)
- bigint_linmul3(z.get_reg(), x.data(), x_sw, y.word_at(0));
+ bigint_linmul3(z.data(), x.data(), x_sw, y.word_at(0));
else if(x_sw && y_sw)
{
- SecureVector<word> workspace(z.size());
- bigint_mul(z.get_reg(), z.size(), workspace,
+ secure_vector<word> workspace(z.size());
+ bigint_mul(z.data(), z.size(), &workspace[0],
x.data(), x.size(), x_sw,
y.data(), y.size(), y_sw);
}
@@ -164,7 +164,7 @@ BigInt operator<<(const BigInt& x, size_t shift)
const size_t x_sw = x.sig_words();
BigInt y(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0));
- bigint_shl2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
+ bigint_shl2(y.data(), x.data(), x_sw, shift_words, shift_bits);
return y;
}
@@ -183,7 +183,7 @@ BigInt operator>>(const BigInt& x, size_t shift)
x_sw = x.sig_words();
BigInt y(x.sign(), x_sw - shift_words);
- bigint_shr2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
+ bigint_shr2(y.data(), x.data(), x_sw, shift_words, shift_bits);
return y;
}
diff --git a/src/math/bigint/big_rand.cpp b/src/math/bigint/big_rand.cpp
index 7cddb2de0..a6776a296 100644
--- a/src/math/bigint/big_rand.cpp
+++ b/src/math/bigint/big_rand.cpp
@@ -35,7 +35,7 @@ void BigInt::randomize(RandomNumberGenerator& rng,
clear();
else
{
- SecureVector<byte> array = rng.random_vec((bitsize + 7) / 8);
+ secure_vector<byte> array = rng.random_vec((bitsize + 7) / 8);
if(bitsize % 8)
array[0] &= 0xFF >> (8 - (bitsize % 8));
diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp
index e2e062f2d..224a27a48 100644
--- a/src/math/bigint/bigint.cpp
+++ b/src/math/bigint/bigint.cpp
@@ -40,23 +40,12 @@ BigInt::BigInt(Sign s, size_t size)
}
/*
-* Construct a BigInt from a "raw" BigInt
+* Copy constructor
*/
BigInt::BigInt(const BigInt& b)
{
- const size_t b_words = b.sig_words();
-
- if(b_words)
- {
- reg.resize(round_up<size_t>(b_words, 8));
- reg.copy(b.data(), b_words);
- set_sign(b.sign());
- }
- else
- {
- reg.resize(2);
- set_sign(Positive);
- }
+ reg = b.get_reg();
+ set_sign(b.sign());
}
/*
@@ -101,15 +90,6 @@ BigInt::BigInt(RandomNumberGenerator& rng, size_t bits)
}
/*
-* Swap this BigInt with another
-*/
-void BigInt::swap(BigInt& other)
- {
- reg.swap(other.reg);
- std::swap(signedness, other.signedness);
- }
-
-/*
* Grow the internal storage
*/
void BigInt::grow_reg(size_t n)
@@ -233,8 +213,7 @@ 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 i = top_word + 1; i != size(); ++i)
- reg[i] = 0;
+ clear_mem(&reg[top_word+1], size() - (top_word + 1));
reg[top_word] &= mask;
}
@@ -365,12 +344,4 @@ void BigInt::binary_decode(const byte buf[], size_t length)
reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[i];
}
-/*
-* Set this number to the value in buf
-*/
-void BigInt::binary_decode(const MemoryRegion<byte>& buf)
- {
- binary_decode(buf, buf.size());
- }
-
}
diff --git a/src/math/bigint/bigint.h b/src/math/bigint/bigint.h
index 87c7cb766..98b98bd6f 100644
--- a/src/math/bigint/bigint.h
+++ b/src/math/bigint/bigint.h
@@ -314,22 +314,29 @@ class BOTAN_DLL BigInt
* @result a pointer to the start of the internal register of
* the integer value
*/
+ word* data() { return &reg[0]; }
+
+ /**
+ * Return a pointer to the big integer word register
+ * @result a pointer to the start of the internal register of
+ * the integer value
+ */
const word* data() const { return &reg[0]; }
/**
* return a reference to the internal register containing the value
- * @result a reference to the word-array (SecureVector<word>)
+ * @result a reference to the word-array (secure_vector<word>)
* with the internal register value (containing the integer
* value)
*/
- SecureVector<word>& get_reg() { return reg; }
+ secure_vector<word>& get_reg() { return reg; }
/**
* return a const reference to the internal register containing the value
- * @result a const reference to the word-array (SecureVector<word>)
+ * @result a const reference to the word-array (secure_vector<word>)
* with the internal register value (containing the integer value)
*/
- const SecureVector<word>& get_reg() const { return reg; }
+ const secure_vector<word>& get_reg() const { return reg; }
/**
* Assign using a plain word array
@@ -369,10 +376,13 @@ class BOTAN_DLL BigInt
void binary_decode(const byte buf[], size_t length);
/**
- * Read integer value from a byte array (MemoryRegion<byte>)
+ * Read integer value from a byte array (secure_vector<byte>)
* @param buf the array to load from
*/
- void binary_decode(const MemoryRegion<byte>& buf);
+ void binary_decode(const secure_vector<byte>& buf)
+ {
+ binary_decode(&buf[0], buf.size());
+ }
/**
* @param base the base to measure the size for
@@ -391,12 +401,21 @@ class BOTAN_DLL BigInt
const BigInt& max);
/**
- * Encode the integer value from a BigInt to a SecureVector of bytes
+ * Encode the integer value from a BigInt to a std::vector of bytes
+ * @param n the BigInt to use as integer source
+ * @param base number-base of resulting byte array representation
+ * @result secure_vector of bytes containing the integer with given base
+ */
+ static std::vector<byte> encode(const BigInt& n, Base base = Binary);
+
+ /**
+ * Encode the integer value from a BigInt to a secure_vector of bytes
* @param n the BigInt to use as integer source
* @param base number-base of resulting byte array representation
- * @result SecureVector of bytes containing the integer with given base
+ * @result secure_vector of bytes containing the integer with given base
*/
- static SecureVector<byte> encode(const BigInt& n, Base base = Binary);
+ static secure_vector<byte> encode_locked(const BigInt& n,
+ Base base = Binary);
/**
* Encode the integer value from a BigInt to a byte array
@@ -423,22 +442,41 @@ class BOTAN_DLL BigInt
* @param base number-base of the integer in buf
* @result BigInt representing the integer in the byte array
*/
- static BigInt decode(const MemoryRegion<byte>& buf,
- Base base = Binary);
+ static BigInt decode(const secure_vector<byte>& buf,
+ Base base = Binary)
+ {
+ return BigInt::decode(&buf[0], buf.size(), base);
+ }
+
+ /**
+ * Create a BigInt from an integer in a byte array
+ * @param buf the binary value to load
+ * @param base number-base of the integer in buf
+ * @result BigInt representing the integer in the byte array
+ */
+ static BigInt decode(const std::vector<byte>& buf,
+ Base base = Binary)
+ {
+ return BigInt::decode(&buf[0], buf.size(), base);
+ }
/**
* Encode a BigInt to a byte array according to IEEE 1363
* @param n the BigInt to encode
- * @param bytes the length of the resulting SecureVector<byte>
- * @result a SecureVector<byte> containing the encoded BigInt
+ * @param bytes the length of the resulting secure_vector<byte>
+ * @result a secure_vector<byte> containing the encoded BigInt
*/
- static SecureVector<byte> encode_1363(const BigInt& n, size_t bytes);
+ static secure_vector<byte> encode_1363(const BigInt& n, size_t bytes);
/**
* Swap this value with another
* @param other BigInt to swap values with
*/
- void swap(BigInt& other);
+ void swap(BigInt& other)
+ {
+ reg.swap(other.reg);
+ std::swap(signedness, other.signedness);
+ }
/**
* Create empty BigInt
@@ -500,8 +538,31 @@ class BOTAN_DLL BigInt
*/
BigInt(NumberType type, size_t n);
+ /**
+ * Move constructor
+ */
+ BigInt(BigInt&& other)
+ {
+ this->swap(other);
+ }
+
+ /**
+ * Move assignment
+ */
+ BigInt& operator=(BigInt&& other)
+ {
+ if(this != &other)
+ this->swap(other);
+
+ return (*this);
+ }
+
+ /**
+ * Copy assignment
+ */
+ BigInt& operator=(const BigInt&) = default;
private:
- SecureVector<word> reg;
+ secure_vector<word> reg;
Sign signedness;
};
diff --git a/src/math/ec_gfp/point_gfp.cpp b/src/math/ec_gfp/point_gfp.cpp
index 7ac6b4141..599b6e842 100644
--- a/src/math/ec_gfp/point_gfp.cpp
+++ b/src/math/ec_gfp/point_gfp.cpp
@@ -45,7 +45,7 @@ void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const
const size_t p_size = curve.get_p_words();
const word p_dash = curve.get_p_dash();
- SecureVector<word>& z_reg = z.get_reg();
+ secure_vector<word>& z_reg = z.get_reg();
z_reg.resize(2*p_size+1);
zeroise(z_reg);
@@ -71,7 +71,7 @@ void PointGFp::monty_sqr(BigInt& z, const BigInt& x) const
const size_t p_size = curve.get_p_words();
const word p_dash = curve.get_p_dash();
- SecureVector<word>& z_reg = z.get_reg();
+ secure_vector<word>& z_reg = z.get_reg();
z_reg.resize(2*p_size+1);
zeroise(z_reg);
@@ -479,22 +479,22 @@ bool PointGFp::operator==(const PointGFp& other) const
}
// encoding and decoding
-SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
+secure_vector<byte> EC2OSP(const PointGFp& point, byte format)
{
if(point.is_zero())
- return SecureVector<byte>(1); // single 0 byte
+ return secure_vector<byte>(1); // single 0 byte
const size_t p_bytes = point.get_curve().get_p().bytes();
BigInt x = point.get_affine_x();
BigInt y = point.get_affine_y();
- SecureVector<byte> bX = BigInt::encode_1363(x, p_bytes);
- SecureVector<byte> bY = BigInt::encode_1363(y, p_bytes);
+ secure_vector<byte> bX = BigInt::encode_1363(x, p_bytes);
+ secure_vector<byte> bY = BigInt::encode_1363(y, p_bytes);
if(format == PointGFp::UNCOMPRESSED)
{
- SecureVector<byte> result;
+ secure_vector<byte> result;
result.push_back(0x04);
result += bX;
@@ -504,7 +504,7 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
}
else if(format == PointGFp::COMPRESSED)
{
- SecureVector<byte> result;
+ secure_vector<byte> result;
result.push_back(0x02 | static_cast<byte>(y.get_bit(0)));
result += bX;
@@ -513,7 +513,7 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
}
else if(format == PointGFp::HYBRID)
{
- SecureVector<byte> result;
+ secure_vector<byte> result;
result.push_back(0x06 | static_cast<byte>(y.get_bit(0)));
result += bX;
@@ -591,7 +591,7 @@ PointGFp OS2ECP(const byte data[], size_t data_len,
throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
}
else
- throw Invalid_Argument("OS2ECP: Unknown format type");
+ throw Invalid_Argument("OS2ECP: Unknown format type " + std::to_string(pc));
PointGFp result(curve, x, y);
diff --git a/src/math/ec_gfp/point_gfp.h b/src/math/ec_gfp/point_gfp.h
index b2b6fe2f0..017f66e1c 100644
--- a/src/math/ec_gfp/point_gfp.h
+++ b/src/math/ec_gfp/point_gfp.h
@@ -59,6 +59,34 @@ class BOTAN_DLL PointGFp
PointGFp(const CurveGFp& curve);
/**
+ * Copy constructor
+ */
+ PointGFp(const PointGFp&) = default;
+
+ /**
+ * Move Constructor
+ */
+ PointGFp(PointGFp&& other)
+ {
+ this->swap(other);
+ }
+
+ /**
+ * Standard Assignment
+ */
+ PointGFp& operator=(const PointGFp&) = default;
+
+ /**
+ * Move Assignment
+ */
+ PointGFp& operator=(PointGFp&& other)
+ {
+ if(this != &other)
+ this->swap(other);
+ return (*this);
+ }
+
+ /**
* Construct a point from its affine coordinates
* @param curve the base curve
* @param x affine x coordinate
@@ -66,9 +94,6 @@ class BOTAN_DLL PointGFp
*/
PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y);
- //PointGFp(const PointGFp& other) = default;
- //PointGFp& operator=(const PointGFp& other) = default;
-
/**
* += Operator
* @param rhs the PointGFp to add to the local value
@@ -220,7 +245,7 @@ class BOTAN_DLL PointGFp
CurveGFp curve;
BigInt coord_x, coord_y, coord_z;
- mutable SecureVector<word> ws; // workspace for Montgomery
+ mutable secure_vector<word> ws; // workspace for Montgomery
};
// relational operators
@@ -253,12 +278,13 @@ inline PointGFp operator*(const PointGFp& point, const BigInt& scalar)
}
// encoding and decoding
-SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format);
+secure_vector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format);
PointGFp BOTAN_DLL OS2ECP(const byte data[], size_t data_len,
const CurveGFp& curve);
-inline PointGFp OS2ECP(const MemoryRegion<byte>& data, const CurveGFp& curve)
+template<typename Alloc>
+PointGFp OS2ECP(const std::vector<byte, Alloc>& data, const CurveGFp& curve)
{ return OS2ECP(&data[0], data.size(), curve); }
}
diff --git a/src/math/numbertheory/dsa_gen.cpp b/src/math/numbertheory/dsa_gen.cpp
index 670f103da..d30a08f1a 100644
--- a/src/math/numbertheory/dsa_gen.cpp
+++ b/src/math/numbertheory/dsa_gen.cpp
@@ -42,29 +42,29 @@ bool generate_dsa_primes(RandomNumberGenerator& rng,
Algorithm_Factory& af,
BigInt& p, BigInt& q,
size_t pbits, size_t qbits,
- const MemoryRegion<byte>& seed_c)
+ const std::vector<byte>& seed_c)
{
if(!fips186_3_valid_size(pbits, qbits))
throw Invalid_Argument(
"FIPS 186-3 does not allow DSA domain parameters of " +
- to_string(pbits) + "/" + to_string(qbits) + " bits long");
+ std::to_string(pbits) + "/" + std::to_string(qbits) + " bits long");
if(seed_c.size() * 8 < qbits)
throw Invalid_Argument(
- "Generating a DSA parameter set with a " + to_string(qbits) +
+ "Generating a DSA parameter set with a " + std::to_string(qbits) +
"long q requires a seed at least as many bits long");
- std::auto_ptr<HashFunction> hash(
- af.make_hash_function("SHA-" + to_string(qbits)));
+ std::unique_ptr<HashFunction> hash(
+ af.make_hash_function("SHA-" + std::to_string(qbits)));
const size_t HASH_SIZE = hash->output_length();
class Seed
{
public:
- Seed(const MemoryRegion<byte>& s) : seed(s) {}
+ Seed(const std::vector<byte>& s) : seed(s) {}
- operator MemoryRegion<byte>& () { return seed; }
+ operator std::vector<byte>& () { return seed; }
Seed& operator++()
{
@@ -74,7 +74,7 @@ bool generate_dsa_primes(RandomNumberGenerator& rng,
return (*this);
}
private:
- SecureVector<byte> seed;
+ std::vector<byte> seed;
};
Seed seed(seed_c);
@@ -90,7 +90,7 @@ bool generate_dsa_primes(RandomNumberGenerator& rng,
b = (pbits-1) % (HASH_SIZE * 8);
BigInt X;
- SecureVector<byte> V(HASH_SIZE * (n+1));
+ std::vector<byte> V(HASH_SIZE * (n+1));
for(size_t j = 0; j != 4096; ++j)
{
@@ -116,14 +116,15 @@ bool generate_dsa_primes(RandomNumberGenerator& rng,
/*
* Generate DSA Primes
*/
-SecureVector<byte> generate_dsa_primes(RandomNumberGenerator& rng,
- Algorithm_Factory& af,
- BigInt& p, BigInt& q,
- size_t pbits, size_t qbits)
+std::vector<byte> generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p, BigInt& q,
+ size_t pbits, size_t qbits)
{
while(true)
{
- SecureVector<byte> seed = rng.random_vec(qbits / 8);
+ std::vector<byte> seed(qbits / 8);
+ rng.randomize(&seed[0], seed.size());
if(generate_dsa_primes(rng, af, p, q, pbits, qbits, seed))
return seed;
diff --git a/src/math/numbertheory/make_prm.cpp b/src/math/numbertheory/make_prm.cpp
index 4fb3f908c..dc94420ab 100644
--- a/src/math/numbertheory/make_prm.cpp
+++ b/src/math/numbertheory/make_prm.cpp
@@ -20,7 +20,7 @@ BigInt random_prime(RandomNumberGenerator& rng,
{
if(bits <= 1)
throw Invalid_Argument("random_prime: Can't make a prime of " +
- to_string(bits) + " bits");
+ std::to_string(bits) + " bits");
else if(bits == 2)
return ((rng.next_byte() % 2) ? 2 : 3);
else if(bits == 3)
@@ -48,7 +48,7 @@ BigInt random_prime(RandomNumberGenerator& rng,
p += (modulo - p % modulo) + equiv;
const size_t sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
- SecureVector<size_t> sieve(sieve_size);
+ secure_vector<u16bit> sieve(sieve_size);
for(size_t j = 0; j != sieve.size(); ++j)
sieve[j] = p % PRIMES[j];
@@ -88,7 +88,7 @@ BigInt random_safe_prime(RandomNumberGenerator& rng, size_t bits)
{
if(bits <= 64)
throw Invalid_Argument("random_safe_prime: Can't make a prime of " +
- to_string(bits) + " bits");
+ std::to_string(bits) + " bits");
BigInt p;
do
diff --git a/src/math/numbertheory/mp_numth.cpp b/src/math/numbertheory/mp_numth.cpp
index 23623b5f0..b10fe2639 100644
--- a/src/math/numbertheory/mp_numth.cpp
+++ b/src/math/numbertheory/mp_numth.cpp
@@ -20,9 +20,9 @@ BigInt square(const BigInt& x)
const size_t x_sw = x.sig_words();
BigInt z(BigInt::Positive, round_up<size_t>(2*x_sw, 16));
- SecureVector<word> workspace(z.size());
+ secure_vector<word> workspace(z.size());
- bigint_sqr(z.get_reg(), z.size(), workspace,
+ bigint_sqr(z.data(), z.size(), &workspace[0],
x.data(), x.size(), x_sw);
return z;
}
@@ -44,13 +44,13 @@ BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c)
const size_t c_sw = c.sig_words();
BigInt r(sign, std::max(a.size() + b.size(), c_sw) + 1);
- SecureVector<word> workspace(r.size());
+ secure_vector<word> workspace(r.size());
- bigint_mul(r.get_reg(), r.size(), workspace,
+ bigint_mul(r.data(), r.size(), &workspace[0],
a.data(), a.size(), a_sw,
b.data(), b.size(), b_sw);
const size_t r_size = std::max(r.sig_words(), c_sw);
- bigint_add2(r.get_reg(), r_size, c.data(), c_sw);
+ bigint_add2(r.data(), r_size, c.data(), c_sw);
return r;
}
diff --git a/src/math/numbertheory/numthry.cpp b/src/math/numbertheory/numthry.cpp
index c7896c17a..18f6ce429 100644
--- a/src/math/numbertheory/numthry.cpp
+++ b/src/math/numbertheory/numthry.cpp
@@ -83,7 +83,7 @@ size_t miller_rabin_test_iterations(size_t bits, size_t level)
{
struct mapping { size_t bits; size_t verify_iter; size_t check_iter; };
- static const mapping tests[] = {
+ const mapping tests[] = {
{ 50, 55, 25 },
{ 100, 38, 22 },
{ 160, 32, 18 },
diff --git a/src/math/numbertheory/numthry.h b/src/math/numbertheory/numthry.h
index 750fbc78e..d21635f34 100644
--- a/src/math/numbertheory/numthry.h
+++ b/src/math/numbertheory/numthry.h
@@ -189,7 +189,7 @@ class Algorithm_Factory;
* @param qbits how long q will be in bits
* @return random seed used to generate this parameter set
*/
-SecureVector<byte> BOTAN_DLL
+std::vector<byte> BOTAN_DLL
generate_dsa_primes(RandomNumberGenerator& rng,
Algorithm_Factory& af,
BigInt& p_out, BigInt& q_out,
@@ -212,7 +212,7 @@ generate_dsa_primes(RandomNumberGenerator& rng,
Algorithm_Factory& af,
BigInt& p_out, BigInt& q_out,
size_t pbits, size_t qbits,
- const MemoryRegion<byte>& seed);
+ const std::vector<byte>& seed);
/**
* The size of the PRIMES[] array
diff --git a/src/math/numbertheory/pow_mod.cpp b/src/math/numbertheory/pow_mod.cpp
index bf6b29275..c7d7fe70e 100644
--- a/src/math/numbertheory/pow_mod.cpp
+++ b/src/math/numbertheory/pow_mod.cpp
@@ -16,7 +16,7 @@ namespace Botan {
*/
Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints)
{
- core = 0;
+ core = nullptr;
set_modulus(n, hints);
}
@@ -25,7 +25,7 @@ Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints)
*/
Power_Mod::Power_Mod(const Power_Mod& other)
{
- core = 0;
+ core = nullptr;
if(other.core)
core = other.core->copy();
}
@@ -36,7 +36,7 @@ Power_Mod::Power_Mod(const Power_Mod& other)
Power_Mod& Power_Mod::operator=(const Power_Mod& other)
{
delete core;
- core = 0;
+ core = nullptr;
if(other.core)
core = other.core->copy();
return (*this);
@@ -56,7 +56,7 @@ Power_Mod::~Power_Mod()
void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const
{
delete core;
- core = 0;
+ core = nullptr;
if(n != 0)
{
diff --git a/src/math/numbertheory/pow_mod.h b/src/math/numbertheory/pow_mod.h
index 7ec237d72..9857c1833 100644
--- a/src/math/numbertheory/pow_mod.h
+++ b/src/math/numbertheory/pow_mod.h
@@ -61,7 +61,7 @@ class BOTAN_DLL Power_Mod
Power_Mod(const BigInt& = 0, Usage_Hints = NO_HINTS);
Power_Mod(const Power_Mod&);
- ~Power_Mod();
+ virtual ~Power_Mod();
private:
mutable Modular_Exponentiator* core;
Usage_Hints hints;
diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp
index 8993f4ba9..0db5455a7 100644
--- a/src/math/numbertheory/powm_mnt.cpp
+++ b/src/math/numbertheory/powm_mnt.cpp
@@ -29,8 +29,8 @@ void Montgomery_Exponentiator::set_base(const BigInt& base)
g.resize((1 << window_bits) - 1);
- SecureVector<word> z(2 * (mod_words + 1));
- SecureVector<word> workspace(z.size());
+ secure_vector<word> z(2 * (mod_words + 1));
+ secure_vector<word> workspace(z.size());
g[0] = (base >= modulus) ? (base % modulus) : base;
@@ -69,8 +69,8 @@ BigInt Montgomery_Exponentiator::execute() const
const size_t exp_nibbles = (exp_bits + window_bits - 1) / window_bits;
BigInt x = R_mod;
- SecureVector<word> z(2 * (mod_words + 1));
- SecureVector<word> workspace(2 * (mod_words + 1));
+ secure_vector<word> z(2 * (mod_words + 1));
+ secure_vector<word> workspace(2 * (mod_words + 1));
for(size_t i = exp_nibbles; i > 0; --i)
{
diff --git a/src/mutex/info.txt b/src/mutex/info.txt
deleted file mode 100644
index af4cf9bb3..000000000
--- a/src/mutex/info.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-define MUTEX_WRAPPERS
-
-<header:internal>
-mutex.h
-</header:internal>
diff --git a/src/mutex/mutex.h b/src/mutex/mutex.h
deleted file mode 100644
index f209466d5..000000000
--- a/src/mutex/mutex.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-* Mutex
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MUTEX_H__
-#define BOTAN_MUTEX_H__
-
-#include <botan/exceptn.h>
-
-namespace Botan {
-
-/**
-* Mutex Base Class
-*/
-class Mutex
- {
- public:
- /**
- * Lock the mutex
- */
- virtual void lock() = 0;
-
- /**
- * Unlock the mutex
- */
- virtual void unlock() = 0;
- virtual ~Mutex() {}
- };
-
-/**
-* Mutex Factory
-*/
-class Mutex_Factory
- {
- public:
- /**
- * @return newly allocated mutex
- */
- virtual Mutex* make() = 0;
-
- virtual ~Mutex_Factory() {}
- };
-
-/**
-* Mutex Holding Class for RAII
-*/
-class Mutex_Holder
- {
- public:
- /**
- * Hold onto a mutex until we leave scope
- * @param m the mutex to lock
- */
- Mutex_Holder(Mutex* m) : mux(m)
- {
- if(!mux)
- throw Invalid_Argument("Mutex_Holder: Argument was NULL");
- mux->lock();
- }
-
- ~Mutex_Holder() { mux->unlock(); }
- private:
- Mutex* mux;
- };
-
-}
-
-#endif
diff --git a/src/mutex/noop_mutex/info.txt b/src/mutex/noop_mutex/info.txt
deleted file mode 100644
index 16670b1dd..000000000
--- a/src/mutex/noop_mutex/info.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-define MUTEX_NOOP
-
-<source>
-mux_noop.cpp
-</source>
-
-<header:internal>
-mux_noop.h
-</header:internal>
diff --git a/src/mutex/noop_mutex/mux_noop.cpp b/src/mutex/noop_mutex/mux_noop.cpp
deleted file mode 100644
index 18151274a..000000000
--- a/src/mutex/noop_mutex/mux_noop.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-* No-Op Mutex Factory
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mux_noop.h>
-
-namespace Botan {
-
-/*
-* No-Op Mutex Factory
-*/
-Mutex* Noop_Mutex_Factory::make()
- {
- class Noop_Mutex : public Mutex
- {
- public:
- class Mutex_State_Error : public Internal_Error
- {
- public:
- Mutex_State_Error(const std::string& where) :
- Internal_Error("Noop_Mutex::" + where + ": " +
- "Mutex is already " + where + "ed") {}
- };
-
- void lock()
- {
- if(locked)
- throw Mutex_State_Error("lock");
- locked = true;
- }
-
- void unlock()
- {
- if(!locked)
- throw Mutex_State_Error("unlock");
- locked = false;
- }
-
- Noop_Mutex() { locked = false; }
- private:
- bool locked;
- };
-
- return new Noop_Mutex;
- }
-
-}
diff --git a/src/mutex/noop_mutex/mux_noop.h b/src/mutex/noop_mutex/mux_noop.h
deleted file mode 100644
index 20989a635..000000000
--- a/src/mutex/noop_mutex/mux_noop.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-* No-Op Mutex Factory
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_NOOP_MUTEX_FACTORY_H__
-#define BOTAN_NOOP_MUTEX_FACTORY_H__
-
-#include <botan/internal/mutex.h>
-
-namespace Botan {
-
-/**
-* No-Op Mutex Factory
-*/
-class Noop_Mutex_Factory : public Mutex_Factory
- {
- public:
- Mutex* make();
- };
-
-}
-
-#endif
diff --git a/src/mutex/pthreads/info.txt b/src/mutex/pthreads/info.txt
deleted file mode 100644
index 1d826b61c..000000000
--- a/src/mutex/pthreads/info.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-define MUTEX_PTHREAD
-
-<source>
-mux_pthr.cpp
-</source>
-
-<header:internal>
-mux_pthr.h
-</header:internal>
-
-<libs>
-all!qnx,freebsd,dragonfly,openbsd,netbsd -> pthread
-</libs>
-
-<os>
-aix
-cygwin
-darwin
-freebsd
-dragonfly
-hpux
-irix
-linux
-netbsd
-openbsd
-qnx
-solaris
-tru64
-</os>
diff --git a/src/mutex/pthreads/mux_pthr.cpp b/src/mutex/pthreads/mux_pthr.cpp
deleted file mode 100644
index 165132239..000000000
--- a/src/mutex/pthreads/mux_pthr.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* Pthread Mutex
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mux_pthr.h>
-#include <botan/exceptn.h>
-
-#ifndef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 199506
-#endif
-
-#include <pthread.h>
-
-namespace Botan {
-
-/*
-* Pthread Mutex Factory
-*/
-Mutex* Pthread_Mutex_Factory::make()
- {
-
- class Pthread_Mutex : public Mutex
- {
- public:
- void lock()
- {
- if(pthread_mutex_lock(&mutex) != 0)
- throw Invalid_State("Pthread_Mutex::lock: Error occured");
- }
-
- void unlock()
- {
- if(pthread_mutex_unlock(&mutex) != 0)
- throw Invalid_State("Pthread_Mutex::unlock: Error occured");
- }
-
- Pthread_Mutex()
- {
- if(pthread_mutex_init(&mutex, 0) != 0)
- throw Invalid_State("Pthread_Mutex: initialization failed");
- }
-
- ~Pthread_Mutex()
- {
- if(pthread_mutex_destroy(&mutex) != 0)
- throw Invalid_State("~Pthread_Mutex: mutex is still locked");
- }
- private:
- pthread_mutex_t mutex;
- };
-
- return new Pthread_Mutex();
- }
-
-}
diff --git a/src/mutex/pthreads/mux_pthr.h b/src/mutex/pthreads/mux_pthr.h
deleted file mode 100644
index 5cecd09ad..000000000
--- a/src/mutex/pthreads/mux_pthr.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-* Pthread Mutex
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MUTEX_PTHREAD_H__
-#define BOTAN_MUTEX_PTHREAD_H__
-
-#include <botan/internal/mutex.h>
-
-namespace Botan {
-
-/**
-* Pthread Mutex Factory
-*/
-class Pthread_Mutex_Factory : public Mutex_Factory
- {
- public:
- Mutex* make();
- };
-
-}
-
-#endif
diff --git a/src/mutex/qt_mutex/info.txt b/src/mutex/qt_mutex/info.txt
deleted file mode 100644
index 7b014f886..000000000
--- a/src/mutex/qt_mutex/info.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-define MUTEX_QT
-
-load_on request
-
-<source>
-mux_qt.cpp
-</source>
-
-<header:internal>
-mux_qt.h
-</header:internal>
-
-# I think we want to always use qt-mt, not qt -- not much point in supporting
-# mutexes in a single threaded application, after all.
-<libs>
-all -> qt-mt
-</libs>
diff --git a/src/mutex/qt_mutex/mux_qt.cpp b/src/mutex/qt_mutex/mux_qt.cpp
deleted file mode 100644
index da4e5ce5c..000000000
--- a/src/mutex/qt_mutex/mux_qt.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-* Qt Thread Mutex
-* (C) 2004-2007 Justin Karneges
-* 2004-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mux_qt.h>
-#include <qmutex.h>
-
-#if !defined(QT_THREAD_SUPPORT)
- #error Your version of Qt does not support threads or mutexes
-#endif
-
-namespace Botan {
-
-/*
-* Qt Mutex Factory
-*/
-Mutex* Qt_Mutex_Factory::make()
- {
- class Qt_Mutex : public Mutex
- {
- public:
- void lock() { mutex.lock(); }
- void unlock() { mutex.unlock(); }
- private:
- QMutex mutex;
- };
-
- return new Qt_Mutex();
- }
-
-}
diff --git a/src/mutex/qt_mutex/mux_qt.h b/src/mutex/qt_mutex/mux_qt.h
deleted file mode 100644
index 3805acc3b..000000000
--- a/src/mutex/qt_mutex/mux_qt.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-* Qt Mutex
-* (C) 2004-2007 Justin Karneges
-* 2004-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MUTEX_QT_H__
-#define BOTAN_MUTEX_QT_H__
-
-#include <botan/internal/mutex.h>
-
-namespace Botan {
-
-/**
-* Qt Mutex
-*/
-class Qt_Mutex_Factory : public Mutex_Factory
- {
- public:
- Mutex* make();
- };
-
-}
-
-#endif
diff --git a/src/mutex/win32_crit_section/info.txt b/src/mutex/win32_crit_section/info.txt
deleted file mode 100644
index d90b8b64b..000000000
--- a/src/mutex/win32_crit_section/info.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-define MUTEX_WIN32
-
-<source>
-mux_win32.cpp
-</source>
-
-<header:internal>
-mux_win32.h
-</header:internal>
-
-<os>
-cygwin
-windows
-mingw
-</os>
diff --git a/src/mutex/win32_crit_section/mux_win32.cpp b/src/mutex/win32_crit_section/mux_win32.cpp
deleted file mode 100644
index fa6051798..000000000
--- a/src/mutex/win32_crit_section/mux_win32.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* Win32 Mutex
-* (C) 2006 Luca Piccarreta
-* 2006-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mux_win32.h>
-#include <windows.h>
-
-namespace Botan {
-
-/*
-* Win32 Mutex Factory
-*/
-Mutex* Win32_Mutex_Factory::make()
- {
- class Win32_Mutex : public Mutex
- {
- public:
- void lock() { EnterCriticalSection(&mutex); }
- void unlock() { LeaveCriticalSection(&mutex); }
-
- Win32_Mutex() { InitializeCriticalSection(&mutex); }
- ~Win32_Mutex() { DeleteCriticalSection(&mutex); }
- private:
- CRITICAL_SECTION mutex;
- };
-
- return new Win32_Mutex();
- }
-
-}
diff --git a/src/mutex/win32_crit_section/mux_win32.h b/src/mutex/win32_crit_section/mux_win32.h
deleted file mode 100644
index 2aa51e18b..000000000
--- a/src/mutex/win32_crit_section/mux_win32.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-* Win32 Mutex
-* (C) 2006 Luca Piccarreta
-* 2006-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MUTEX_WIN32_H__
-#define BOTAN_MUTEX_WIN32_H__
-
-#include <botan/internal/mutex.h>
-
-namespace Botan {
-
-/**
-* Win32 Mutex Factory
-*/
-class Win32_Mutex_Factory : public Mutex_Factory
- {
- public:
- Mutex* make();
- };
-}
-
-#endif
diff --git a/src/passhash/bcrypt/bcrypt.cpp b/src/passhash/bcrypt/bcrypt.cpp
index bb2e9095a..eeb99399f 100644
--- a/src/passhash/bcrypt/bcrypt.cpp
+++ b/src/passhash/bcrypt/bcrypt.cpp
@@ -54,7 +54,7 @@ std::string bcrypt_base64_encode(const byte input[], size_t length)
return b64;
}
-MemoryVector<byte> bcrypt_base64_decode(std::string input)
+std::vector<byte> bcrypt_base64_decode(std::string input)
{
const byte OPENBSD_BASE64_SUB[256] = {
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
@@ -84,11 +84,11 @@ 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);
+ return unlock(base64_decode(input));
}
std::string make_bcrypt(const std::string& pass,
- const MemoryRegion<byte>& salt,
+ const std::vector<byte>& salt,
u16bit work_factor)
{
const byte magic[24] = {
@@ -97,14 +97,14 @@ std::string make_bcrypt(const std::string& pass,
0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74
};
- MemoryVector<byte> ctext(magic, 24);
+ std::vector<byte> ctext(magic, magic + sizeof(magic));
Blowfish blowfish;
// Include the trailing NULL byte
blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()),
pass.length() + 1,
- salt,
+ &salt[0],
work_factor);
for(size_t i = 0; i != 64; ++i)
@@ -112,8 +112,13 @@ std::string make_bcrypt(const std::string& pass,
std::string salt_b64 = bcrypt_base64_encode(&salt[0], salt.size());
- return "$2a$" + to_string(work_factor, 2) + "$" + salt_b64.substr(0, 22) +
- bcrypt_base64_encode(&ctext[0], ctext.size() - 1);
+ std::string work_factor_str = std::to_string(work_factor);
+ if(work_factor_str.length() == 1)
+ work_factor_str = "0" + work_factor_str;
+
+ return "$2a$" + work_factor_str +
+ "$" + salt_b64.substr(0, 22) +
+ bcrypt_base64_encode(&ctext[0], ctext.size() - 1);
}
}
@@ -122,7 +127,7 @@ std::string generate_bcrypt(const std::string& pass,
RandomNumberGenerator& rng,
u16bit work_factor)
{
- return make_bcrypt(pass, rng.random_vec(16), work_factor);
+ return make_bcrypt(pass, unlock(rng.random_vec(16)), work_factor);
}
bool check_bcrypt(const std::string& pass, const std::string& hash)
@@ -136,7 +141,7 @@ bool check_bcrypt(const std::string& pass, const std::string& hash)
const u16bit workfactor = to_u32bit(hash.substr(4, 2));
- MemoryVector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
+ std::vector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
const std::string compare = make_bcrypt(pass, salt, workfactor);
diff --git a/src/passhash/passhash9/passhash9.cpp b/src/passhash/passhash9/passhash9.cpp
index e1e37da1e..af7ed761b 100644
--- a/src/passhash/passhash9/passhash9.cpp
+++ b/src/passhash/passhash9/passhash9.cpp
@@ -40,7 +40,7 @@ MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
}
catch(Algorithm_Not_Found) {}
- return 0;
+ return nullptr;
}
}
@@ -53,17 +53,18 @@ std::string generate_passhash9(const std::string& pass,
MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
if(!prf)
- throw Invalid_Argument("Passhash9: Algorithm id " + to_string(alg_id) +
+ throw Invalid_Argument("Passhash9: Algorithm id " +
+ std::to_string(alg_id) +
" is not defined");
PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer
- SecureVector<byte> salt(SALT_BYTES);
+ secure_vector<byte> salt(SALT_BYTES);
rng.randomize(&salt[0], salt.size());
const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;
- SecureVector<byte> pbkdf2_output =
+ secure_vector<byte> pbkdf2_output =
kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
pass,
&salt[0], salt.size(),
@@ -104,7 +105,7 @@ bool check_passhash9(const std::string& pass, const std::string& hash)
pipe.write(hash.c_str() + MAGIC_PREFIX.size());
pipe.end_msg();
- SecureVector<byte> bin = pipe.read_all();
+ secure_vector<byte> bin = pipe.read_all();
if(bin.size() != BINARY_LENGTH)
return false;
@@ -119,12 +120,12 @@ bool check_passhash9(const std::string& pass, const std::string& hash)
MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);
- if(pbkdf_prf == 0)
+ if(!pbkdf_prf)
return false; // unknown algorithm, reject
PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer
- SecureVector<byte> cmp = kdf.derive_key(
+ secure_vector<byte> cmp = kdf.derive_key(
PASSHASH9_PBKDF_OUTPUT_LEN,
pass,
&bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
diff --git a/src/pbe/pbe.h b/src/pbe/pbe.h
index 9add98872..975f3e6c7 100644
--- a/src/pbe/pbe.h
+++ b/src/pbe/pbe.h
@@ -37,7 +37,7 @@ class BOTAN_DLL PBE : public Filter
* DER encode the params (the number of iterations and the salt value)
* @return encoded params
*/
- virtual MemoryVector<byte> encode_params() const = 0;
+ virtual std::vector<byte> encode_params() const = 0;
/**
* Decode params and use them inside this Filter.
diff --git a/src/pbe/pbes1/pbes1.cpp b/src/pbe/pbes1/pbes1.cpp
index ec5ebb253..0e5e8284c 100644
--- a/src/pbe/pbes1/pbes1.cpp
+++ b/src/pbe/pbes1/pbes1.cpp
@@ -65,7 +65,7 @@ void PBE_PKCS5v15::flush_pipe(bool safe_to_skip)
if(safe_to_skip && pipe.remaining() < 64)
return;
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(pipe.remaining())
{
size_t got = pipe.read(&buffer[0], buffer.size());
@@ -80,7 +80,7 @@ void PBE_PKCS5v15::set_key(const std::string& passphrase)
{
PKCS5_PBKDF1 pbkdf(hash_function->clone());
- SecureVector<byte> key_and_iv = pbkdf.derive_key(16, passphrase,
+ secure_vector<byte> key_and_iv = pbkdf.derive_key(16, passphrase,
&salt[0], salt.size(),
iterations).bits_of();
@@ -102,14 +102,14 @@ void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng)
/*
* Encode PKCS#5 PBES1 parameters
*/
-MemoryVector<byte> PBE_PKCS5v15::encode_params() const
+std::vector<byte> PBE_PKCS5v15::encode_params() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(salt, OCTET_STRING)
.encode(iterations)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
diff --git a/src/pbe/pbes1/pbes1.h b/src/pbe/pbes1/pbes1.h
index e10cbbb53..bbdbd5b9d 100644
--- a/src/pbe/pbes1/pbes1.h
+++ b/src/pbe/pbes1/pbes1.h
@@ -40,7 +40,7 @@ class BOTAN_DLL PBE_PKCS5v15 : public PBE
private:
void set_key(const std::string&);
void new_params(RandomNumberGenerator& rng);
- MemoryVector<byte> encode_params() const;
+ std::vector<byte> encode_params() const;
void decode_params(DataSource&);
OID get_oid() const;
@@ -50,7 +50,7 @@ class BOTAN_DLL PBE_PKCS5v15 : public PBE
BlockCipher* block_cipher;
HashFunction* hash_function;
- SecureVector<byte> salt, key, iv;
+ secure_vector<byte> salt, key, iv;
size_t iterations;
Pipe pipe;
};
diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp
index 85afe6ffe..752a4fb6d 100644
--- a/src/pbe/pbes2/pbes2.cpp
+++ b/src/pbe/pbes2/pbes2.cpp
@@ -72,7 +72,7 @@ void PBE_PKCS5v20::flush_pipe(bool safe_to_skip)
if(safe_to_skip && pipe.remaining() < 64)
return;
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
while(pipe.remaining())
{
size_t got = pipe.read(&buffer[0], buffer.size());
@@ -107,7 +107,7 @@ void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng)
/*
* Encode PKCS#5 PBES2 parameters
*/
-MemoryVector<byte> PBE_PKCS5v20::encode_params() const
+std::vector<byte> PBE_PKCS5v20::encode_params() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -119,18 +119,18 @@ MemoryVector<byte> PBE_PKCS5v20::encode_params() const
.encode(iterations)
.encode(key_length)
.end_cons()
- .get_contents()
+ .get_contents_unlocked()
)
)
.encode(
AlgorithmIdentifier(block_cipher->name() + "/CBC",
DER_Encoder()
.encode(iv, OCTET_STRING)
- .get_contents()
+ .get_contents_unlocked()
)
)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
@@ -228,8 +228,8 @@ PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher,
*/
PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION)
{
- hash_function = 0;
- block_cipher = 0;
+ hash_function = nullptr;
+ block_cipher = nullptr;
decode_params(params);
}
diff --git a/src/pbe/pbes2/pbes2.h b/src/pbe/pbes2/pbes2.h
index 7b82980e5..5593c9091 100644
--- a/src/pbe/pbes2/pbes2.h
+++ b/src/pbe/pbes2/pbes2.h
@@ -49,7 +49,7 @@ class BOTAN_DLL PBE_PKCS5v20 : public PBE
private:
void set_key(const std::string&);
void new_params(RandomNumberGenerator& rng);
- MemoryVector<byte> encode_params() const;
+ std::vector<byte> encode_params() const;
void decode_params(DataSource&);
OID get_oid() const;
@@ -58,7 +58,7 @@ class BOTAN_DLL PBE_PKCS5v20 : public PBE
Cipher_Dir direction;
BlockCipher* block_cipher;
HashFunction* hash_function;
- SecureVector<byte> salt, key, iv;
+ secure_vector<byte> salt, key, iv;
size_t iterations, key_length;
Pipe pipe;
};
diff --git a/src/pbkdf/pbkdf1/pbkdf1.cpp b/src/pbkdf/pbkdf1/pbkdf1.cpp
index 16de435e9..7f0939b8f 100644
--- a/src/pbkdf/pbkdf1/pbkdf1.cpp
+++ b/src/pbkdf/pbkdf1/pbkdf1.cpp
@@ -26,7 +26,7 @@ OctetString PKCS5_PBKDF1::derive_key(size_t key_len,
hash->update(passphrase);
hash->update(salt, salt_size);
- SecureVector<byte> key = hash->final();
+ secure_vector<byte> key = hash->final();
for(size_t j = 1; j != iterations; ++j)
{
diff --git a/src/pbkdf/pbkdf2/pbkdf2.cpp b/src/pbkdf/pbkdf2/pbkdf2.cpp
index 7e4d1cd8a..699ce7c6b 100644
--- a/src/pbkdf/pbkdf2/pbkdf2.cpp
+++ b/src/pbkdf/pbkdf2/pbkdf2.cpp
@@ -30,14 +30,14 @@ OctetString PKCS5_PBKDF2::derive_key(size_t key_len,
catch(Invalid_Key_Length)
{
throw Exception(name() + " cannot accept passphrases of length " +
- to_string(passphrase.length()));
+ std::to_string(passphrase.length()));
}
- SecureVector<byte> key(key_len);
+ secure_vector<byte> key(key_len);
byte* T = &key[0];
- SecureVector<byte> U(mac->output_length());
+ secure_vector<byte> U(mac->output_length());
u32bit counter = 1;
while(key_len)
@@ -48,13 +48,13 @@ OctetString PKCS5_PBKDF2::derive_key(size_t key_len,
mac->update_be(counter);
mac->final(&U[0]);
- xor_buf(T, U, T_size);
+ xor_buf(T, &U[0], T_size);
for(size_t j = 1; j != iterations; ++j)
{
mac->update(U);
mac->final(&U[0]);
- xor_buf(T, U, T_size);
+ xor_buf(T, &U[0], T_size);
}
key_len -= T_size;
diff --git a/src/pbkdf/pgps2k/pgp_s2k.cpp b/src/pbkdf/pgps2k/pgp_s2k.cpp
index 9cec7304c..6f6de58e2 100644
--- a/src/pbkdf/pgps2k/pgp_s2k.cpp
+++ b/src/pbkdf/pgps2k/pgp_s2k.cpp
@@ -17,7 +17,7 @@ OctetString OpenPGP_S2K::derive_key(size_t key_len,
const byte salt_buf[], size_t salt_size,
size_t iterations) const
{
- SecureVector<byte> key(key_len), hash_buf;
+ secure_vector<byte> key(key_len), hash_buf;
size_t pass = 0, generated = 0,
total_size = passphrase.size() + salt_size;
@@ -46,7 +46,7 @@ OctetString OpenPGP_S2K::derive_key(size_t key_len,
}
hash_buf = hash->final();
- key.copy(generated, &hash_buf[0], hash->output_length());
+ buffer_insert(key, generated, &hash_buf[0], hash->output_length());
generated += hash->output_length();
++pass;
}
diff --git a/src/pk_pad/eme.cpp b/src/pk_pad/eme.cpp
index cfdaa240d..f90239d8c 100644
--- a/src/pk_pad/eme.cpp
+++ b/src/pk_pad/eme.cpp
@@ -12,7 +12,7 @@ namespace Botan {
/*
* Encode a message
*/
-SecureVector<byte> EME::encode(const byte msg[], size_t msg_len,
+secure_vector<byte> EME::encode(const byte msg[], size_t msg_len,
size_t key_bits,
RandomNumberGenerator& rng) const
{
@@ -22,7 +22,7 @@ SecureVector<byte> EME::encode(const byte msg[], size_t msg_len,
/*
* Encode a message
*/
-SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
+secure_vector<byte> EME::encode(const secure_vector<byte>& msg,
size_t key_bits,
RandomNumberGenerator& rng) const
{
@@ -32,7 +32,7 @@ SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
/*
* Decode a message
*/
-SecureVector<byte> EME::decode(const byte msg[], size_t msg_len,
+secure_vector<byte> EME::decode(const byte msg[], size_t msg_len,
size_t key_bits) const
{
return unpad(msg, msg_len, key_bits);
@@ -41,7 +41,7 @@ SecureVector<byte> EME::decode(const byte msg[], size_t msg_len,
/*
* Decode a message
*/
-SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg,
+secure_vector<byte> EME::decode(const secure_vector<byte>& msg,
size_t key_bits) const
{
return unpad(&msg[0], msg.size(), key_bits);
diff --git a/src/pk_pad/eme.h b/src/pk_pad/eme.h
index 4e89ef9d3..6f8acaa23 100644
--- a/src/pk_pad/eme.h
+++ b/src/pk_pad/eme.h
@@ -34,7 +34,7 @@ class BOTAN_DLL EME
* @param rng a random number generator
* @return encoded plaintext
*/
- SecureVector<byte> encode(const byte in[],
+ secure_vector<byte> encode(const byte in[],
size_t in_length,
size_t key_length,
RandomNumberGenerator& rng) const;
@@ -46,7 +46,7 @@ class BOTAN_DLL EME
* @param rng a random number generator
* @return encoded plaintext
*/
- SecureVector<byte> encode(const MemoryRegion<byte>& in,
+ secure_vector<byte> encode(const secure_vector<byte>& in,
size_t key_length,
RandomNumberGenerator& rng) const;
@@ -57,7 +57,7 @@ class BOTAN_DLL EME
* @param key_length length of the key in bits
* @return plaintext
*/
- SecureVector<byte> decode(const byte in[],
+ secure_vector<byte> decode(const byte in[],
size_t in_length,
size_t key_length) const;
@@ -67,7 +67,7 @@ class BOTAN_DLL EME
* @param key_length length of the key in bits
* @return plaintext
*/
- SecureVector<byte> decode(const MemoryRegion<byte>& in,
+ secure_vector<byte> decode(const secure_vector<byte>& in,
size_t key_length) const;
virtual ~EME() {}
@@ -80,7 +80,7 @@ class BOTAN_DLL EME
* @param rng a random number generator
* @return encoded plaintext
*/
- virtual SecureVector<byte> pad(const byte in[],
+ virtual secure_vector<byte> pad(const byte in[],
size_t in_length,
size_t key_length,
RandomNumberGenerator& rng) const = 0;
@@ -92,7 +92,7 @@ class BOTAN_DLL EME
* @param key_length length of the key in bits
* @return plaintext
*/
- virtual SecureVector<byte> unpad(const byte in[],
+ virtual secure_vector<byte> unpad(const byte in[],
size_t in_length,
size_t key_length) const = 0;
};
diff --git a/src/pk_pad/eme1/eme1.cpp b/src/pk_pad/eme1/eme1.cpp
index 1cc0c332d..57275d4f9 100644
--- a/src/pk_pad/eme1/eme1.cpp
+++ b/src/pk_pad/eme1/eme1.cpp
@@ -15,7 +15,7 @@ namespace Botan {
/*
* EME1 Pad Operation
*/
-SecureVector<byte> EME1::pad(const byte in[], size_t in_length,
+secure_vector<byte> EME1::pad(const byte in[], size_t in_length,
size_t key_length,
RandomNumberGenerator& rng) const
{
@@ -24,13 +24,13 @@ SecureVector<byte> EME1::pad(const byte in[], size_t in_length,
if(in_length > key_length - 2*Phash.size() - 1)
throw Invalid_Argument("EME1: Input is too large");
- SecureVector<byte> out(key_length);
+ secure_vector<byte> out(key_length);
rng.randomize(&out[0], Phash.size());
- out.copy(Phash.size(), &Phash[0], Phash.size());
+ buffer_insert(out, Phash.size(), &Phash[0], Phash.size());
out[out.size() - in_length - 1] = 0x01;
- out.copy(out.size() - in_length, in, in_length);
+ buffer_insert(out, out.size() - in_length, in, in_length);
mgf->mask(&out[0], Phash.size(),
&out[Phash.size()], out.size() - Phash.size());
@@ -44,7 +44,7 @@ SecureVector<byte> EME1::pad(const byte in[], size_t in_length,
/*
* EME1 Unpad Operation
*/
-SecureVector<byte> EME1::unpad(const byte in[], size_t in_length,
+secure_vector<byte> EME1::unpad(const byte in[], size_t in_length,
size_t key_length) const
{
/*
@@ -65,8 +65,8 @@ SecureVector<byte> EME1::unpad(const byte in[], size_t in_length,
if(in_length > key_length)
in_length = 0;
- SecureVector<byte> input(key_length);
- input.copy(key_length - in_length, in, in_length);
+ secure_vector<byte> input(key_length);
+ buffer_insert(input, key_length - in_length, in, in_length);
mgf->mask(&input[Phash.size()], input.size() - Phash.size(),
&input[0], Phash.size());
@@ -104,8 +104,7 @@ SecureVector<byte> EME1::unpad(const byte in[], size_t in_length,
if(bad_input)
throw Decoding_Error("Invalid EME1 encoding");
- return SecureVector<byte>(input + delim_idx + 1,
- input.size() - delim_idx - 1);
+ return secure_vector<byte>(&input[delim_idx + 1], &input[input.size()]);
}
/*
diff --git a/src/pk_pad/eme1/eme1.h b/src/pk_pad/eme1/eme1.h
index 0d0223de0..eb6fc6bf5 100644
--- a/src/pk_pad/eme1/eme1.h
+++ b/src/pk_pad/eme1/eme1.h
@@ -30,11 +30,11 @@ class BOTAN_DLL EME1 : public EME
~EME1() { delete mgf; }
private:
- SecureVector<byte> pad(const byte[], size_t, size_t,
+ secure_vector<byte> pad(const byte[], size_t, size_t,
RandomNumberGenerator&) const;
- SecureVector<byte> unpad(const byte[], size_t, size_t) const;
+ secure_vector<byte> unpad(const byte[], size_t, size_t) const;
- SecureVector<byte> Phash;
+ secure_vector<byte> Phash;
MGF* mgf;
};
diff --git a/src/pk_pad/eme_pkcs/eme_pkcs.cpp b/src/pk_pad/eme_pkcs/eme_pkcs.cpp
index c4d6838b1..0e7d1fc30 100644
--- a/src/pk_pad/eme_pkcs/eme_pkcs.cpp
+++ b/src/pk_pad/eme_pkcs/eme_pkcs.cpp
@@ -12,7 +12,7 @@ namespace Botan {
/*
* PKCS1 Pad Operation
*/
-SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
+secure_vector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
size_t olen,
RandomNumberGenerator& rng) const
{
@@ -23,13 +23,13 @@ SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
if(inlen > olen - 10)
throw Encoding_Error("PKCS1: Input is too large");
- SecureVector<byte> out(olen);
+ secure_vector<byte> out(olen);
out[0] = 0x02;
for(size_t j = 1; j != olen - inlen - 1; ++j)
while(out[j] == 0)
out[j] = rng.next_byte();
- out.copy(olen - inlen, in, inlen);
+ buffer_insert(out, olen - inlen, in, inlen);
return out;
}
@@ -37,7 +37,7 @@ SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
/*
* PKCS1 Unpad Operation
*/
-SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
+secure_vector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
size_t key_len) const
{
if(inlen != key_len / 8 || inlen < 10 || in[0] != 0x02)
@@ -53,7 +53,7 @@ SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
if(seperator < 9)
throw Decoding_Error("PKCS1::unpad");
- return SecureVector<byte>(in + seperator + 1, inlen - seperator - 1);
+ return secure_vector<byte>(&in[seperator + 1], &in[inlen]);
}
/*
diff --git a/src/pk_pad/eme_pkcs/eme_pkcs.h b/src/pk_pad/eme_pkcs/eme_pkcs.h
index 4c4614bda..2808e18d6 100644
--- a/src/pk_pad/eme_pkcs/eme_pkcs.h
+++ b/src/pk_pad/eme_pkcs/eme_pkcs.h
@@ -20,9 +20,9 @@ class BOTAN_DLL EME_PKCS1v15 : public EME
public:
size_t maximum_input_size(size_t) const;
private:
- SecureVector<byte> pad(const byte[], size_t, size_t,
+ secure_vector<byte> pad(const byte[], size_t, size_t,
RandomNumberGenerator&) const;
- SecureVector<byte> unpad(const byte[], size_t, size_t) const;
+ secure_vector<byte> unpad(const byte[], size_t, size_t) const;
};
}
diff --git a/src/pk_pad/emsa.h b/src/pk_pad/emsa.h
index e943fc5eb..821ca782f 100644
--- a/src/pk_pad/emsa.h
+++ b/src/pk_pad/emsa.h
@@ -29,7 +29,7 @@ class BOTAN_DLL EMSA
/**
* @return raw hash
*/
- virtual SecureVector<byte> raw_data() = 0;
+ virtual secure_vector<byte> raw_data() = 0;
/**
* Return the encoding of a message
@@ -38,7 +38,7 @@ class BOTAN_DLL EMSA
* @param rng a random number generator
* @return encoded signature
*/
- virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>& msg,
+ virtual secure_vector<byte> encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator& rng) = 0;
@@ -49,8 +49,8 @@ class BOTAN_DLL EMSA
* @param key_bits the size of the key in bits
* @return true if coded is a valid encoding of raw, otherwise false
*/
- virtual bool verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw,
+ virtual bool verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw,
size_t key_bits) = 0;
virtual ~EMSA() {}
};
diff --git a/src/pk_pad/emsa1/emsa1.cpp b/src/pk_pad/emsa1/emsa1.cpp
index ba861898a..7f9a1885f 100644
--- a/src/pk_pad/emsa1/emsa1.cpp
+++ b/src/pk_pad/emsa1/emsa1.cpp
@@ -11,7 +11,7 @@ namespace Botan {
namespace {
-SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg,
+secure_vector<byte> emsa1_encoding(const secure_vector<byte>& msg,
size_t output_bits)
{
if(8*msg.size() <= output_bits)
@@ -20,7 +20,7 @@ SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg,
size_t shift = 8*msg.size() - output_bits;
size_t byte_shift = shift / 8, bit_shift = shift % 8;
- SecureVector<byte> digest(msg.size() - byte_shift);
+ secure_vector<byte> digest(msg.size() - byte_shift);
for(size_t j = 0; j != msg.size() - byte_shift; ++j)
digest[j] = msg[j];
@@ -51,7 +51,7 @@ void EMSA1::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA1::raw_data()
+secure_vector<byte> EMSA1::raw_data()
{
return hash->final();
}
@@ -59,7 +59,7 @@ SecureVector<byte> EMSA1::raw_data()
/*
* EMSA1 Encode Operation
*/
-SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA1::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
@@ -71,14 +71,14 @@ SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg,
/*
* EMSA1 Decode/Verify Operation
*/
-bool EMSA1::verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw, size_t key_bits)
+bool EMSA1::verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw, size_t key_bits)
{
try {
if(raw.size() != hash->output_length())
throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
- SecureVector<byte> our_coding = emsa1_encoding(raw, key_bits);
+ secure_vector<byte> our_coding = emsa1_encoding(raw, key_bits);
if(our_coding == coded) return true;
if(our_coding[0] != 0) return false;
diff --git a/src/pk_pad/emsa1/emsa1.h b/src/pk_pad/emsa1/emsa1.h
index 120cb0cd3..f84ca5ae7 100644
--- a/src/pk_pad/emsa1/emsa1.h
+++ b/src/pk_pad/emsa1/emsa1.h
@@ -32,12 +32,12 @@ class BOTAN_DLL EMSA1 : public EMSA
const HashFunction* hash_ptr() const { return hash; }
private:
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
HashFunction* hash;
diff --git a/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp b/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp
index bbcc5aae7..9096edfbf 100644
--- a/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp
+++ b/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp
@@ -13,7 +13,7 @@ namespace Botan {
/*
* EMSA1 BSI Encode Operation
*/
-SecureVector<byte> EMSA1_BSI::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA1_BSI::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
diff --git a/src/pk_pad/emsa1_bsi/emsa1_bsi.h b/src/pk_pad/emsa1_bsi/emsa1_bsi.h
index 51ed6bc00..1b90f48df 100644
--- a/src/pk_pad/emsa1_bsi/emsa1_bsi.h
+++ b/src/pk_pad/emsa1_bsi/emsa1_bsi.h
@@ -26,7 +26,7 @@ class BOTAN_DLL EMSA1_BSI : public EMSA1
*/
EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {}
private:
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
};
diff --git a/src/pk_pad/emsa2/emsa2.cpp b/src/pk_pad/emsa2/emsa2.cpp
index 96ac8e908..d299ddacd 100644
--- a/src/pk_pad/emsa2/emsa2.cpp
+++ b/src/pk_pad/emsa2/emsa2.cpp
@@ -15,9 +15,9 @@ namespace {
/*
* EMSA2 Encode Operation
*/
-SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg,
+secure_vector<byte> emsa2_encoding(const secure_vector<byte>& msg,
size_t output_bits,
- const MemoryRegion<byte>& empty_hash,
+ const secure_vector<byte>& empty_hash,
byte hash_id)
{
const size_t HASH_SIZE = empty_hash.size();
@@ -34,12 +34,12 @@ SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg,
if(empty_hash[j] != msg[j])
empty = false;
- SecureVector<byte> output(output_length);
+ secure_vector<byte> output(output_length);
output[0] = (empty ? 0x4B : 0x6B);
output[output_length - 3 - HASH_SIZE] = 0xBA;
set_mem(&output[1], output_length - 4 - HASH_SIZE, 0xBB);
- output.copy(output_length - (HASH_SIZE + 2), &msg[0], msg.size());
+ buffer_insert(output, output_length - (HASH_SIZE + 2), &msg[0], msg.size());
output[output_length-2] = hash_id;
output[output_length-1] = 0xCC;
@@ -59,7 +59,7 @@ void EMSA2::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA2::raw_data()
+secure_vector<byte> EMSA2::raw_data()
{
return hash->final();
}
@@ -67,7 +67,7 @@ SecureVector<byte> EMSA2::raw_data()
/*
* EMSA2 Encode Operation
*/
-SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA2::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
@@ -77,8 +77,8 @@ SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg,
/*
* EMSA2 Verify Operation
*/
-bool EMSA2::verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw,
+bool EMSA2::verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw,
size_t key_bits)
{
try
diff --git a/src/pk_pad/emsa2/emsa2.h b/src/pk_pad/emsa2/emsa2.h
index 9e0fa6a95..fb0cecb21 100644
--- a/src/pk_pad/emsa2/emsa2.h
+++ b/src/pk_pad/emsa2/emsa2.h
@@ -27,15 +27,15 @@ class BOTAN_DLL EMSA2 : public EMSA
~EMSA2() { delete hash; }
private:
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
- SecureVector<byte> empty_hash;
+ secure_vector<byte> empty_hash;
HashFunction* hash;
byte hash_id;
};
diff --git a/src/pk_pad/emsa3/emsa3.cpp b/src/pk_pad/emsa3/emsa3.cpp
index a381a82f6..0d603c508 100644
--- a/src/pk_pad/emsa3/emsa3.cpp
+++ b/src/pk_pad/emsa3/emsa3.cpp
@@ -15,7 +15,7 @@ namespace {
/*
* EMSA3 Encode Operation
*/
-SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg,
+secure_vector<byte> emsa3_encoding(const secure_vector<byte>& msg,
size_t output_bits,
const byte hash_id[],
size_t hash_id_length)
@@ -24,14 +24,14 @@ SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg,
if(output_length < hash_id_length + msg.size() + 10)
throw Encoding_Error("emsa3_encoding: Output length is too small");
- SecureVector<byte> T(output_length);
+ secure_vector<byte> T(output_length);
const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2;
T[0] = 0x01;
set_mem(&T[1], P_LENGTH, 0xFF);
T[P_LENGTH+1] = 0x00;
- T.copy(P_LENGTH+2, hash_id, hash_id_length);
- T.copy(output_length-msg.size(), &msg[0], msg.size());
+ buffer_insert(T, P_LENGTH+2, hash_id, hash_id_length);
+ buffer_insert(T, output_length-msg.size(), &msg[0], msg.size());
return T;
}
@@ -48,7 +48,7 @@ void EMSA3::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA3::raw_data()
+secure_vector<byte> EMSA3::raw_data()
{
return hash->final();
}
@@ -56,7 +56,7 @@ SecureVector<byte> EMSA3::raw_data()
/*
* EMSA3 Encode Operation
*/
-SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA3::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
@@ -70,8 +70,8 @@ SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg,
/*
* Default signature decoding
*/
-bool EMSA3::verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw,
+bool EMSA3::verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw,
size_t key_bits)
{
if(raw.size() != hash->output_length())
@@ -115,9 +115,9 @@ void EMSA3_Raw::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA3_Raw::raw_data()
+secure_vector<byte> EMSA3_Raw::raw_data()
{
- SecureVector<byte> ret;
+ secure_vector<byte> ret;
std::swap(ret, message);
return ret;
}
@@ -125,23 +125,23 @@ SecureVector<byte> EMSA3_Raw::raw_data()
/*
* EMSA3_Raw Encode Operation
*/
-SecureVector<byte> EMSA3_Raw::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA3_Raw::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator&)
{
- return emsa3_encoding(msg, output_bits, 0, 0);
+ return emsa3_encoding(msg, output_bits, nullptr, 0);
}
/*
* Default signature decoding
*/
-bool EMSA3_Raw::verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw,
+bool EMSA3_Raw::verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw,
size_t key_bits)
{
try
{
- return (coded == emsa3_encoding(raw, key_bits, 0, 0));
+ return (coded == emsa3_encoding(raw, key_bits, nullptr, 0));
}
catch(...)
{
diff --git a/src/pk_pad/emsa3/emsa3.h b/src/pk_pad/emsa3/emsa3.h
index 5faf9d7e5..9fbda67ee 100644
--- a/src/pk_pad/emsa3/emsa3.h
+++ b/src/pk_pad/emsa3/emsa3.h
@@ -29,16 +29,16 @@ class BOTAN_DLL EMSA3 : public EMSA
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
private:
HashFunction* hash;
- SecureVector<byte> hash_id;
+ std::vector<byte> hash_id;
};
/**
@@ -51,16 +51,16 @@ class BOTAN_DLL EMSA3_Raw : public EMSA
public:
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
private:
- SecureVector<byte> message;
+ secure_vector<byte> message;
};
}
diff --git a/src/pk_pad/emsa4/emsa4.cpp b/src/pk_pad/emsa4/emsa4.cpp
index ef88e1953..c8b8cbc6a 100644
--- a/src/pk_pad/emsa4/emsa4.cpp
+++ b/src/pk_pad/emsa4/emsa4.cpp
@@ -22,7 +22,7 @@ void EMSA4::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA4::raw_data()
+secure_vector<byte> EMSA4::raw_data()
{
return hash->final();
}
@@ -30,7 +30,7 @@ SecureVector<byte> EMSA4::raw_data()
/*
* EMSA4 Encode Operation
*/
-SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA4::encoding_of(const secure_vector<byte>& msg,
size_t output_bits,
RandomNumberGenerator& rng)
{
@@ -43,21 +43,21 @@ SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg,
const size_t output_length = (output_bits + 7) / 8;
- SecureVector<byte> salt = rng.random_vec(SALT_SIZE);
+ secure_vector<byte> salt = rng.random_vec(SALT_SIZE);
for(size_t j = 0; j != 8; ++j)
hash->update(0);
hash->update(msg);
- hash->update(salt, SALT_SIZE);
- SecureVector<byte> H = hash->final();
+ hash->update(salt);
+ secure_vector<byte> H = hash->final();
- SecureVector<byte> EM(output_length);
+ secure_vector<byte> EM(output_length);
EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
- EM.copy(output_length - 1 - HASH_SIZE - SALT_SIZE, salt, SALT_SIZE);
- mgf->mask(H, HASH_SIZE, EM, output_length - HASH_SIZE - 1);
+ buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
+ mgf->mask(&H[0], HASH_SIZE, &EM[0], output_length - HASH_SIZE - 1);
EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
- EM.copy(output_length - 1 - HASH_SIZE, H, HASH_SIZE);
+ buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
EM[output_length-1] = 0xBC;
return EM;
@@ -66,26 +66,29 @@ SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg,
/*
* EMSA4 Decode/Verify Operation
*/
-bool EMSA4::verify(const MemoryRegion<byte>& const_coded,
- const MemoryRegion<byte>& raw, size_t key_bits)
+bool EMSA4::verify(const secure_vector<byte>& const_coded,
+ const secure_vector<byte>& raw, size_t key_bits)
{
const size_t HASH_SIZE = hash->output_length();
const size_t KEY_BYTES = (key_bits + 7) / 8;
if(key_bits < 8*HASH_SIZE + 9)
return false;
+
if(raw.size() != HASH_SIZE)
return false;
- if(const_coded.size() > KEY_BYTES)
+
+ if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1)
return false;
+
if(const_coded[const_coded.size()-1] != 0xBC)
return false;
- SecureVector<byte> coded = const_coded;
+ secure_vector<byte> coded = const_coded;
if(coded.size() < KEY_BYTES)
{
- SecureVector<byte> temp(KEY_BYTES);
- temp.copy(KEY_BYTES - coded.size(), coded, coded.size());
+ secure_vector<byte> temp(KEY_BYTES);
+ buffer_insert(temp, KEY_BYTES - coded.size(), coded);
coded = temp;
}
@@ -93,14 +96,17 @@ bool EMSA4::verify(const MemoryRegion<byte>& const_coded,
if(TOP_BITS > 8 - high_bit(coded[0]))
return false;
- SecureVector<byte> DB(&coded[0], coded.size() - HASH_SIZE - 1);
- SecureVector<byte> H(&coded[coded.size() - HASH_SIZE - 1], HASH_SIZE);
+ byte* DB = &coded[0];
+ const size_t DB_size = coded.size() - HASH_SIZE - 1;
- mgf->mask(H, H.size(), DB, coded.size() - H.size() - 1);
+ const byte* H = &coded[DB_size];
+ const size_t H_size = HASH_SIZE;
+
+ mgf->mask(&H[0], H_size, &DB[0], DB_size);
DB[0] &= 0xFF >> TOP_BITS;
size_t salt_offset = 0;
- for(size_t j = 0; j != DB.size(); ++j)
+ for(size_t j = 0; j != DB_size; ++j)
{
if(DB[j] == 0x01)
{ salt_offset = j + 1; break; }
@@ -110,15 +116,13 @@ bool EMSA4::verify(const MemoryRegion<byte>& const_coded,
if(salt_offset == 0)
return false;
- SecureVector<byte> salt(&DB[salt_offset], DB.size() - salt_offset);
-
for(size_t j = 0; j != 8; ++j)
hash->update(0);
hash->update(raw);
- hash->update(salt);
- SecureVector<byte> H2 = hash->final();
+ hash->update(&DB[salt_offset], DB_size - salt_offset);
+ secure_vector<byte> H2 = hash->final();
- return (H == H2);
+ return same_mem(&H[0], &H2[0], HASH_SIZE);
}
/*
diff --git a/src/pk_pad/emsa4/emsa4.h b/src/pk_pad/emsa4/emsa4.h
index bd8b32ca1..44bf5a429 100644
--- a/src/pk_pad/emsa4/emsa4.h
+++ b/src/pk_pad/emsa4/emsa4.h
@@ -34,11 +34,11 @@ class BOTAN_DLL EMSA4 : public EMSA
~EMSA4() { delete hash; delete mgf; }
private:
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator& rng);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
size_t SALT_SIZE;
diff --git a/src/pk_pad/emsa_raw/emsa_raw.cpp b/src/pk_pad/emsa_raw/emsa_raw.cpp
index d0f3918dd..cb0f99e9c 100644
--- a/src/pk_pad/emsa_raw/emsa_raw.cpp
+++ b/src/pk_pad/emsa_raw/emsa_raw.cpp
@@ -20,9 +20,9 @@ void EMSA_Raw::update(const byte input[], size_t length)
/*
* Return the raw (unencoded) data
*/
-SecureVector<byte> EMSA_Raw::raw_data()
+secure_vector<byte> EMSA_Raw::raw_data()
{
- SecureVector<byte> output;
+ secure_vector<byte> output;
std::swap(message, output);
return output;
}
@@ -30,7 +30,7 @@ SecureVector<byte> EMSA_Raw::raw_data()
/*
* EMSA-Raw Encode Operation
*/
-SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg,
+secure_vector<byte> EMSA_Raw::encoding_of(const secure_vector<byte>& msg,
size_t,
RandomNumberGenerator&)
{
@@ -40,8 +40,8 @@ SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg,
/*
* EMSA-Raw Verify Operation
*/
-bool EMSA_Raw::verify(const MemoryRegion<byte>& coded,
- const MemoryRegion<byte>& raw,
+bool EMSA_Raw::verify(const secure_vector<byte>& coded,
+ const secure_vector<byte>& raw,
size_t)
{
if(coded.size() == raw.size())
diff --git a/src/pk_pad/emsa_raw/emsa_raw.h b/src/pk_pad/emsa_raw/emsa_raw.h
index 2ccd076f2..8ab763575 100644
--- a/src/pk_pad/emsa_raw/emsa_raw.h
+++ b/src/pk_pad/emsa_raw/emsa_raw.h
@@ -20,14 +20,14 @@ class BOTAN_DLL EMSA_Raw : public EMSA
{
private:
void update(const byte[], size_t);
- SecureVector<byte> raw_data();
+ secure_vector<byte> raw_data();
- SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
+ secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t,
RandomNumberGenerator&);
- bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ bool verify(const secure_vector<byte>&, const secure_vector<byte>&,
size_t);
- SecureVector<byte> message;
+ secure_vector<byte> message;
};
}
diff --git a/src/pk_pad/hash_id/hash_id.cpp b/src/pk_pad/hash_id/hash_id.cpp
index 74653cb83..a60e53352 100644
--- a/src/pk_pad/hash_id/hash_id.cpp
+++ b/src/pk_pad/hash_id/hash_id.cpp
@@ -57,32 +57,51 @@ const byte TIGER_PKCS_ID[] = {
/*
* HashID as specified by PKCS
*/
-MemoryVector<byte> pkcs_hash_id(const std::string& name)
+std::vector<byte> pkcs_hash_id(const std::string& name)
{
// Special case for SSL/TLS RSA signatures
if(name == "Parallel(MD5,SHA-160)")
- return MemoryVector<byte>();
+ return std::vector<byte>();
if(name == "MD2")
- return MemoryVector<byte>(MD2_PKCS_ID, sizeof(MD2_PKCS_ID));
+ return std::vector<byte>(MD2_PKCS_ID,
+ MD2_PKCS_ID + sizeof(MD2_PKCS_ID));
+
if(name == "MD5")
- return MemoryVector<byte>(MD5_PKCS_ID, sizeof(MD5_PKCS_ID));
+ return std::vector<byte>(MD5_PKCS_ID,
+ MD5_PKCS_ID + sizeof(MD5_PKCS_ID));
+
if(name == "RIPEMD-128")
- return MemoryVector<byte>(RIPEMD_128_PKCS_ID, sizeof(RIPEMD_128_PKCS_ID));
+ return std::vector<byte>(RIPEMD_128_PKCS_ID,
+ RIPEMD_128_PKCS_ID + sizeof(RIPEMD_128_PKCS_ID));
+
if(name == "RIPEMD-160")
- return MemoryVector<byte>(RIPEMD_160_PKCS_ID, sizeof(RIPEMD_160_PKCS_ID));
+ return std::vector<byte>(RIPEMD_160_PKCS_ID,
+ RIPEMD_160_PKCS_ID + sizeof(RIPEMD_160_PKCS_ID));
+
if(name == "SHA-160")
- return MemoryVector<byte>(SHA_160_PKCS_ID, sizeof(SHA_160_PKCS_ID));
+ return std::vector<byte>(SHA_160_PKCS_ID,
+ SHA_160_PKCS_ID + sizeof(SHA_160_PKCS_ID));
+
if(name == "SHA-224")
- return MemoryVector<byte>(SHA_224_PKCS_ID, sizeof(SHA_224_PKCS_ID));
+ return std::vector<byte>(SHA_224_PKCS_ID,
+ SHA_224_PKCS_ID + sizeof(SHA_224_PKCS_ID));
+
if(name == "SHA-256")
- return MemoryVector<byte>(SHA_256_PKCS_ID, sizeof(SHA_256_PKCS_ID));
+ return std::vector<byte>(SHA_256_PKCS_ID,
+ SHA_256_PKCS_ID + sizeof(SHA_256_PKCS_ID));
+
if(name == "SHA-384")
- return MemoryVector<byte>(SHA_384_PKCS_ID, sizeof(SHA_384_PKCS_ID));
+ return std::vector<byte>(SHA_384_PKCS_ID,
+ SHA_384_PKCS_ID + sizeof(SHA_384_PKCS_ID));
+
if(name == "SHA-512")
- return MemoryVector<byte>(SHA_512_PKCS_ID, sizeof(SHA_512_PKCS_ID));
+ return std::vector<byte>(SHA_512_PKCS_ID,
+ SHA_512_PKCS_ID + sizeof(SHA_512_PKCS_ID));
+
if(name == "Tiger(24,3)")
- return MemoryVector<byte>(TIGER_PKCS_ID, sizeof(TIGER_PKCS_ID));
+ return std::vector<byte>(TIGER_PKCS_ID,
+ TIGER_PKCS_ID + sizeof(TIGER_PKCS_ID));
throw Invalid_Argument("No PKCS #1 identifier for " + name);
}
diff --git a/src/pk_pad/hash_id/hash_id.h b/src/pk_pad/hash_id/hash_id.h
index 909cc6b19..070e7ddb9 100644
--- a/src/pk_pad/hash_id/hash_id.h
+++ b/src/pk_pad/hash_id/hash_id.h
@@ -20,7 +20,7 @@ namespace Botan {
* @return byte sequence identifying the hash
* @throw Invalid_Argument if the hash has no known PKCS #1 hash id
*/
-BOTAN_DLL MemoryVector<byte> pkcs_hash_id(const std::string& hash_name);
+BOTAN_DLL std::vector<byte> pkcs_hash_id(const std::string& hash_name);
/**
* Return the IEEE 1363 hash identifier
diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp
index d58fece12..04941af73 100644
--- a/src/pubkey/dh/dh.cpp
+++ b/src/pubkey/dh/dh.cpp
@@ -24,9 +24,9 @@ DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
/*
* Return the public value for key agreement
*/
-MemoryVector<byte> DH_PublicKey::public_value() const
+std::vector<byte> DH_PublicKey::public_value() const
{
- return BigInt::encode_1363(y, group_p().bytes());
+ return unlock(BigInt::encode_1363(y, group_p().bytes()));
}
/*
@@ -58,7 +58,7 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
* Load a DH private key
*/
DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
{
@@ -71,7 +71,7 @@ DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
/*
* Return the public value for key agreement
*/
-MemoryVector<byte> DH_PrivateKey::public_value() const
+std::vector<byte> DH_PrivateKey::public_value() const
{
return DH_PublicKey::public_value();
}
@@ -83,7 +83,7 @@ DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) :
blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p);
}
-SecureVector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len)
+secure_vector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len)
{
BigInt input = BigInt::decode(w, w_len);
diff --git a/src/pubkey/dh/dh.h b/src/pubkey/dh/dh.h
index 497238417..bf02ffdb9 100644
--- a/src/pubkey/dh/dh.h
+++ b/src/pubkey/dh/dh.h
@@ -23,13 +23,13 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
public:
std::string algo_name() const { return "DH"; }
- MemoryVector<byte> public_value() const;
+ std::vector<byte> public_value() const;
size_t max_input_bits() const { return group_p().bits(); }
DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
DH_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {}
/**
@@ -50,7 +50,7 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
public virtual DL_Scheme_PrivateKey
{
public:
- MemoryVector<byte> public_value() const;
+ std::vector<byte> public_value() const;
/**
* Load a DH private key
@@ -59,7 +59,7 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
* @param rng a random number generator
*/
DH_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng);
/**
@@ -80,7 +80,7 @@ class BOTAN_DLL DH_KA_Operation : public PK_Ops::Key_Agreement
public:
DH_KA_Operation(const DH_PrivateKey& key);
- SecureVector<byte> agree(const byte w[], size_t w_len);
+ secure_vector<byte> agree(const byte w[], size_t w_len);
private:
const BigInt& p;
diff --git a/src/pubkey/dl_algo/dl_algo.cpp b/src/pubkey/dl_algo/dl_algo.cpp
index 8e326ef6a..1034a3252 100644
--- a/src/pubkey/dl_algo/dl_algo.cpp
+++ b/src/pubkey/dl_algo/dl_algo.cpp
@@ -18,13 +18,13 @@ AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const
group.DER_encode(group_format()));
}
-MemoryVector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const
+std::vector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const
{
- return DER_Encoder().encode(y).get_contents();
+ return DER_Encoder().encode(y).get_contents_unlocked();
}
DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
DL_Group::Format format)
{
DataSource_Memory source(alg_id.parameters);
@@ -33,13 +33,13 @@ DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
BER_Decoder(key_bits).decode(y);
}
-MemoryVector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const
+secure_vector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const
{
return DER_Encoder().encode(x).get_contents();
}
DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
DL_Group::Format format)
{
DataSource_Memory source(alg_id.parameters);
diff --git a/src/pubkey/dl_algo/dl_algo.h b/src/pubkey/dl_algo/dl_algo.h
index 2cc632caa..af2806b02 100644
--- a/src/pubkey/dl_algo/dl_algo.h
+++ b/src/pubkey/dl_algo/dl_algo.h
@@ -24,7 +24,7 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
AlgorithmIdentifier algorithm_identifier() const;
- MemoryVector<byte> x509_subject_public_key() const;
+ std::vector<byte> x509_subject_public_key() const;
/**
* Get the DL domain parameters of this key.
@@ -62,7 +62,7 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
virtual DL_Group::Format group_format() const = 0;
DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
DL_Group::Format group_format);
protected:
@@ -94,10 +94,10 @@ class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
*/
const BigInt& get_x() const { return x; }
- MemoryVector<byte> pkcs8_private_key() const;
+ secure_vector<byte> pkcs8_private_key() const;
DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
DL_Group::Format group_format);
protected:
diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp
index 7f0160b6b..93bbcbb2d 100644
--- a/src/pubkey/dl_group/dl_group.cpp
+++ b/src/pubkey/dl_group/dl_group.cpp
@@ -47,7 +47,7 @@ DL_Group::DL_Group(RandomNumberGenerator& rng,
PrimeType type, size_t pbits, size_t qbits)
{
if(pbits < 512)
- throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) +
+ throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) +
" is too small");
if(type == Strong)
@@ -90,7 +90,8 @@ DL_Group::DL_Group(RandomNumberGenerator& rng,
* DL_Group Constructor
*/
DL_Group::DL_Group(RandomNumberGenerator& rng,
- const MemoryRegion<byte>& seed, size_t pbits, size_t qbits)
+ const std::vector<byte>& seed,
+ size_t pbits, size_t qbits)
{
if(!generate_dsa_primes(rng,
global_state().algorithm_factory(),
@@ -202,7 +203,7 @@ const BigInt& DL_Group::get_q() const
/*
* DER encode the parameters
*/
-SecureVector<byte> DL_Group::DER_encode(Format format) const
+std::vector<byte> DL_Group::DER_encode(Format format) const
{
init_check();
@@ -217,7 +218,7 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const
.encode(q)
.encode(g)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
else if(format == ANSI_X9_42)
{
@@ -227,7 +228,7 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const
.encode(g)
.encode(q)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
else if(format == PKCS_3)
{
@@ -236,10 +237,10 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const
.encode(p)
.encode(g)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
- throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
}
/*
@@ -247,7 +248,8 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const
*/
std::string DL_Group::PEM_encode(Format format) const
{
- SecureVector<byte> encoding = DER_encode(format);
+ const std::vector<byte> encoding = DER_encode(format);
+
if(format == PKCS_3)
return PEM_Code::encode(encoding, "DH PARAMETERS");
else if(format == ANSI_X9_57)
@@ -255,7 +257,7 @@ std::string DL_Group::PEM_encode(Format format) const
else if(format == ANSI_X9_42)
return PEM_Code::encode(encoding, "X942 DH PARAMETERS");
else
- throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
}
/*
@@ -289,7 +291,7 @@ void DL_Group::BER_decode(DataSource& source, Format format)
.discard_remaining();
}
else
- throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
initialize(new_p, new_q, new_g);
}
diff --git a/src/pubkey/dl_group/dl_group.h b/src/pubkey/dl_group/dl_group.h
index bfc2c04e5..aa90388ae 100644
--- a/src/pubkey/dl_group/dl_group.h
+++ b/src/pubkey/dl_group/dl_group.h
@@ -77,7 +77,7 @@ class BOTAN_DLL DL_Group
* @param format the encoding format
* @return string holding the DER encoded group
*/
- SecureVector<byte> DER_encode(Format format) const;
+ std::vector<byte> DER_encode(Format format) const;
/**
* Decode a DER/BER encoded group into this instance.
@@ -131,7 +131,8 @@ class BOTAN_DLL DL_Group
* @param pbits the desired bit size of the prime p
* @param qbits the desired bit size of the prime q.
*/
- DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed,
+ DL_Group(RandomNumberGenerator& rng,
+ const std::vector<byte>& seed,
size_t pbits = 1024, size_t qbits = 0);
/**
diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp
index 2b3f65d06..715b55a36 100644
--- a/src/pubkey/dlies/dlies.cpp
+++ b/src/pubkey/dlies/dlies.cpp
@@ -34,19 +34,19 @@ DLIES_Encryptor::~DLIES_Encryptor()
/*
* DLIES Encryption
*/
-SecureVector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
- RandomNumberGenerator&) const
+std::vector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
+ RandomNumberGenerator&) const
{
if(length > maximum_input_size())
throw Invalid_Argument("DLIES: Plaintext too large");
if(other_key.empty())
throw Invalid_State("DLIES: The other key was never set");
- SecureVector<byte> out(my_key.size() + length + mac->output_length());
- out.copy(&my_key[0], my_key.size());
- out.copy(my_key.size(), in, length);
+ secure_vector<byte> out(my_key.size() + length + mac->output_length());
+ buffer_insert(out, 0, my_key);
+ buffer_insert(out, my_key.size(), in, length);
- SecureVector<byte> vz = my_key;
+ secure_vector<byte> vz(my_key.begin(), my_key.end());
vz += ka.derive_key(0, other_key).bits_of();
const size_t K_LENGTH = length + mac_keylen;
@@ -65,13 +65,13 @@ SecureVector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
mac->final(C + length);
- return out;
+ return unlock(out);
}
/*
* Set the other parties public key
*/
-void DLIES_Encryptor::set_other_key(const MemoryRegion<byte>& ok)
+void DLIES_Encryptor::set_other_key(const std::vector<byte>& ok)
{
other_key = ok;
}
@@ -108,18 +108,21 @@ DLIES_Decryptor::~DLIES_Decryptor()
/*
* DLIES Decryption
*/
-SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
+secure_vector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
{
if(length < my_key.size() + mac->output_length())
throw Decoding_Error("DLIES decryption: ciphertext is too short");
const size_t CIPHER_LEN = length - my_key.size() - mac->output_length();
- SecureVector<byte> v(msg, my_key.size());
- SecureVector<byte> C(msg + my_key.size(), CIPHER_LEN);
- SecureVector<byte> T(msg + my_key.size() + CIPHER_LEN, mac->output_length());
+ std::vector<byte> v(msg, msg + my_key.size());
- SecureVector<byte> vz(msg, my_key.size());
+ secure_vector<byte> C(msg + my_key.size(), msg + my_key.size() + CIPHER_LEN);
+
+ secure_vector<byte> T(msg + my_key.size() + CIPHER_LEN,
+ msg + my_key.size() + CIPHER_LEN + mac->output_length());
+
+ secure_vector<byte> vz(msg, msg + my_key.size());
vz += ka.derive_key(0, v).bits_of();
const size_t K_LENGTH = C.size() + mac_keylen;
@@ -131,7 +134,7 @@ SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
mac->update(C);
for(size_t j = 0; j != 8; ++j)
mac->update(0);
- SecureVector<byte> T2 = mac->final();
+ secure_vector<byte> T2 = mac->final();
if(T != T2)
throw Decoding_Error("DLIES: message authentication failed");
diff --git a/src/pubkey/dlies/dlies.h b/src/pubkey/dlies/dlies.h
index 8e5c05852..9739afeb2 100644
--- a/src/pubkey/dlies/dlies.h
+++ b/src/pubkey/dlies/dlies.h
@@ -27,13 +27,14 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
~DLIES_Encryptor();
- void set_other_key(const MemoryRegion<byte>&);
+ void set_other_key(const std::vector<byte>&);
private:
- SecureVector<byte> enc(const byte[], size_t,
- RandomNumberGenerator&) const;
+ std::vector<byte> enc(const byte[], size_t,
+ RandomNumberGenerator&) const;
+
size_t maximum_input_size() const;
- SecureVector<byte> other_key, my_key;
+ std::vector<byte> other_key, my_key;
PK_Key_Agreement ka;
KDF* kdf;
@@ -55,9 +56,9 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
~DLIES_Decryptor();
private:
- SecureVector<byte> dec(const byte[], size_t) const;
+ secure_vector<byte> dec(const byte[], size_t) const;
- SecureVector<byte> my_key;
+ std::vector<byte> my_key;
PK_Key_Agreement ka;
KDF* kdf;
diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp
index 5e511840f..5d56d6b89 100644
--- a/src/pubkey/dsa/dsa.cpp
+++ b/src/pubkey/dsa/dsa.cpp
@@ -8,7 +8,7 @@
#include <botan/dsa.h>
#include <botan/numthry.h>
#include <botan/keypair.h>
-
+#include <future>
namespace Botan {
/*
@@ -42,7 +42,7 @@ DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
}
DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
{
@@ -73,7 +73,7 @@ DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
{
}
-SecureVector<byte>
+secure_vector<byte>
DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -89,11 +89,15 @@ DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
k.randomize(rng, q.bits());
while(k >= q);
- r = mod_q.reduce(powermod_g_p(k));
- s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i));
+ auto future_r = std::async(std::launch::async,
+ [&]() { return mod_q.reduce(powermod_g_p(k)); });
+
+ s = inverse_mod(k, q);
+ r = future_r.get();
+ s = mod_q.multiply(s, mul_add(x, r, i));
}
- SecureVector<byte> output(2*q.bytes());
+ secure_vector<byte> output(2*q.bytes());
r.binary_encode(&output[output.size() / 2 - r.bytes()]);
s.binary_encode(&output[output.size() - s.bytes()]);
return output;
@@ -124,8 +128,14 @@ bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
return false;
s = inverse_mod(s, q);
- s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)),
- powermod_y_p(mod_q.multiply(s, r)));
+
+ auto future_s_i = std::async(std::launch::async,
+ [&]() { return powermod_g_p(mod_q.multiply(s, i)); });
+
+ BigInt s_r = powermod_y_p(mod_q.multiply(s, r));
+ BigInt s_i = future_s_i.get();
+
+ s = mod_p.multiply(s_i, s_r);
return (mod_q.reduce(s) == r);
}
diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h
index a41a8432c..7d51cfdd0 100644
--- a/src/pubkey/dsa/dsa.h
+++ b/src/pubkey/dsa/dsa.h
@@ -29,7 +29,7 @@ class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey
size_t max_input_bits() const { return group_q().bits(); }
DSA_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
{
}
@@ -47,7 +47,7 @@ class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
{
public:
DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng);
DSA_PrivateKey(RandomNumberGenerator& rng,
@@ -69,7 +69,7 @@ class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return q.bits(); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& q;
diff --git a/src/pubkey/ec_group/ec_group.cpp b/src/pubkey/ec_group/ec_group.cpp
index fe4fae885..88c4616a4 100644
--- a/src/pubkey/ec_group/ec_group.cpp
+++ b/src/pubkey/ec_group/ec_group.cpp
@@ -37,8 +37,8 @@ EC_Group::EC_Group(const std::string& str)
{
DataSource_Memory input(str);
- SecureVector<byte> ber =
- PEM_Code::decode_check_label(input, "EC PARAMETERS");
+ std::vector<byte> ber =
+ unlock(PEM_Code::decode_check_label(input, "EC PARAMETERS"));
*this = EC_Group(ber);
}
@@ -48,7 +48,7 @@ EC_Group::EC_Group(const std::string& str)
}
}
-EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
+EC_Group::EC_Group(const std::vector<byte>& ber_data)
{
BER_Decoder ber(ber_data);
BER_Object obj = ber.get_next_object();
@@ -64,7 +64,7 @@ EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
else if(obj.type_tag == SEQUENCE)
{
BigInt p, a, b;
- SecureVector<byte> sv_base_point;
+ std::vector<byte> sv_base_point;
BER_Decoder(ber_data)
.start_cons(SEQUENCE)
@@ -91,7 +91,7 @@ EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
throw Decoding_Error("Unexpected tag while decoding ECC domain params");
}
-SecureVector<byte>
+std::vector<byte>
EC_Group::DER_encode(EC_Group_Encoding form) const
{
if(form == EC_DOMPAR_ENC_EXPLICIT)
@@ -118,19 +118,19 @@ EC_Group::DER_encode(EC_Group_Encoding form) const
.encode(order)
.encode(cofactor)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
else if(form == EC_DOMPAR_ENC_OID)
- return DER_Encoder().encode(get_oid()).get_contents();
+ return DER_Encoder().encode(get_oid()).get_contents_unlocked();
else if(form == EC_DOMPAR_ENC_IMPLICITCA)
- return DER_Encoder().encode_null().get_contents();
+ return DER_Encoder().encode_null().get_contents_unlocked();
else
throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
}
std::string EC_Group::PEM_encode() const
{
- SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
+ const std::vector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
return PEM_Code::encode(der, "EC PARAMETERS");
}
diff --git a/src/pubkey/ec_group/ec_group.h b/src/pubkey/ec_group/ec_group.h
index 59a1918c0..756c158dc 100644
--- a/src/pubkey/ec_group/ec_group.h
+++ b/src/pubkey/ec_group/ec_group.h
@@ -54,7 +54,7 @@ class BOTAN_DLL EC_Group
* Decode a BER encoded ECC domain parameter set
* @param ber_encoding the bytes of the BER encoding
*/
- EC_Group(const MemoryRegion<byte>& ber_encoding);
+ EC_Group(const std::vector<byte>& ber_encoding);
/**
* Create an EC domain by OID (or throw if unknown)
@@ -63,8 +63,8 @@ class BOTAN_DLL EC_Group
EC_Group(const OID& oid);
/**
- * Create an EC domain from PEM encoding (as from PEM_encode),
- * or from an OID name (eg "secp160r1", or "1.3.132.0.8")
+ * Create an EC domain from PEM encoding (as from PEM_encode), or
+ * from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7")
* @param pem_or_oid PEM-encoded data, or an OID
*/
EC_Group(const std::string& pem_or_oid = "");
@@ -74,7 +74,7 @@ class BOTAN_DLL EC_Group
* @param form of encoding to use
* @returns bytes encododed as DER
*/
- SecureVector<byte> DER_encode(EC_Group_Encoding form) const;
+ std::vector<byte> DER_encode(EC_Group_Encoding form) const;
/**
* Return the PEM encoding (always in explicit form)
diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp
index 991446f07..ead129ec6 100644
--- a/src/pubkey/ecc_key/ecc_key.cpp
+++ b/src/pubkey/ecc_key/ecc_key.cpp
@@ -28,7 +28,7 @@ EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
}
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
domain_params = EC_Group(alg_id.parameters);
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
@@ -47,9 +47,9 @@ AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const
return AlgorithmIdentifier(get_oid(), DER_domain());
}
-MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const
+std::vector<byte> EC_PublicKey::x509_subject_public_key() const
{
- return EC2OSP(public_point(), PointGFp::COMPRESSED);
+ return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED));
}
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
@@ -96,7 +96,7 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
"ECC private key was not on the curve");
}
-MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
+secure_vector<byte> EC_PrivateKey::pkcs8_private_key() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -108,7 +108,7 @@ MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
}
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
domain_params = EC_Group(alg_id.parameters);
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h
index cccc8d53c..76a63a7e4 100644
--- a/src/pubkey/ecc_key/ecc_key.h
+++ b/src/pubkey/ecc_key/ecc_key.h
@@ -34,7 +34,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key
const PointGFp& pub_point);
EC_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
/**
* Get the public point of this key.
@@ -46,7 +46,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key
AlgorithmIdentifier algorithm_identifier() const;
- MemoryVector<byte> x509_subject_public_key() const;
+ std::vector<byte> x509_subject_public_key() const;
bool check_key(RandomNumberGenerator& rng,
bool strong) const;
@@ -69,7 +69,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key
* Return the DER encoding of this keys domain in whatever format
* is preset for this particular key
*/
- MemoryVector<byte> DER_domain() const
+ std::vector<byte> DER_domain() const
{ return domain().DER_encode(domain_format()); }
/**
@@ -98,9 +98,9 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey,
const BigInt& private_key);
EC_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
- MemoryVector<byte> pkcs8_private_key() const;
+ secure_vector<byte> pkcs8_private_key() const;
/**
* Get the private key value of this key object.
diff --git a/src/pubkey/ecdh/ecdh.cpp b/src/pubkey/ecdh/ecdh.cpp
index 656644370..511dd0678 100644
--- a/src/pubkey/ecdh/ecdh.cpp
+++ b/src/pubkey/ecdh/ecdh.cpp
@@ -20,7 +20,7 @@ ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) :
key.private_value();
}
-SecureVector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len)
+secure_vector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len)
{
PointGFp point = OS2ECP(w, w_len, curve);
diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h
index 6fe0697bf..0c5d4e010 100644
--- a/src/pubkey/ecdh/ecdh.h
+++ b/src/pubkey/ecdh/ecdh.h
@@ -23,7 +23,7 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey
public:
ECDH_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
EC_PublicKey(alg_id, key_bits) {}
/**
@@ -52,8 +52,8 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey
/**
* @return public point value
*/
- MemoryVector<byte> public_value() const
- { return EC2OSP(public_point(), PointGFp::UNCOMPRESSED); }
+ std::vector<byte> public_value() const
+ { return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED)); }
protected:
ECDH_PublicKey() {}
@@ -69,7 +69,7 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey,
public:
ECDH_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
@@ -83,7 +83,7 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey,
const BigInt& x = 0) :
EC_PrivateKey(rng, domain, x) {}
- MemoryVector<byte> public_value() const
+ std::vector<byte> public_value() const
{ return ECDH_PublicKey::public_value(); }
};
@@ -95,7 +95,7 @@ class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement
public:
ECDH_KA_Operation(const ECDH_PrivateKey& key);
- SecureVector<byte> agree(const byte w[], size_t w_len);
+ secure_vector<byte> agree(const byte w[], size_t w_len);
private:
const CurveGFp& curve;
const BigInt& cofactor;
diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp
index 5c45c5ed3..6ff082649 100644
--- a/src/pubkey/ecdsa/ecdsa.cpp
+++ b/src/pubkey/ecdsa/ecdsa.cpp
@@ -32,7 +32,7 @@ ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecd
{
}
-SecureVector<byte>
+secure_vector<byte>
ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -56,7 +56,7 @@ ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m));
}
- SecureVector<byte> output(2*order.bytes());
+ secure_vector<byte> output(2*order.bytes());
r.binary_encode(&output[output.size() / 2 - r.bytes()]);
s.binary_encode(&output[output.size() - s.bytes()]);
return output;
diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h
index f0834abd8..e37fa1562 100644
--- a/src/pubkey/ecdsa/ecdsa.h
+++ b/src/pubkey/ecdsa/ecdsa.h
@@ -33,7 +33,7 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey
EC_PublicKey(dom_par, public_point) {}
ECDSA_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
EC_PublicKey(alg_id, key_bits) {}
/**
@@ -72,7 +72,7 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
* @param key_bits PKCS #8 structure
*/
ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
@@ -97,7 +97,7 @@ class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature
public:
ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa);
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
size_t message_parts() const { return 2; }
diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp
index 6d15aed79..3988f3155 100644
--- a/src/pubkey/elgamal/elgamal.cpp
+++ b/src/pubkey/elgamal/elgamal.cpp
@@ -44,7 +44,7 @@ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
}
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
{
@@ -76,7 +76,7 @@ ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicK
mod_p = Modular_Reducer(p);
}
-SecureVector<byte>
+secure_vector<byte>
ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -92,7 +92,7 @@ ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len,
BigInt a = powermod_g_p(k);
BigInt b = mod_p.multiply(m, powermod_y_p(k));
- SecureVector<byte> output(2*p.bytes());
+ secure_vector<byte> output(2*p.bytes());
a.binary_encode(&output[p.bytes() - a.bytes()]);
b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]);
return output;
@@ -109,7 +109,7 @@ ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_Private
blinder = Blinder(k, powermod_x_p(k), p);
}
-SecureVector<byte>
+secure_vector<byte>
ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len)
{
const BigInt& p = mod_p.get_modulus();
@@ -129,7 +129,7 @@ ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len)
BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
- return BigInt::encode(blinder.unblind(r));
+ return BigInt::encode_locked(blinder.unblind(r));
}
}
diff --git a/src/pubkey/elgamal/elgamal.h b/src/pubkey/elgamal/elgamal.h
index 383a4160b..957aa4656 100644
--- a/src/pubkey/elgamal/elgamal.h
+++ b/src/pubkey/elgamal/elgamal.h
@@ -28,7 +28,7 @@ class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey
size_t max_input_bits() const { return (group_p().bits() - 1); }
ElGamal_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
{}
@@ -47,7 +47,7 @@ class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
bool check_key(RandomNumberGenerator& rng, bool) const;
ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng);
ElGamal_PrivateKey(RandomNumberGenerator& rng,
@@ -65,7 +65,7 @@ class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption
ElGamal_Encryption_Operation(const ElGamal_PublicKey& key);
- SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
@@ -83,7 +83,7 @@ class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption
ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key);
- SecureVector<byte> decrypt(const byte msg[], size_t msg_len);
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len);
private:
Fixed_Exponent_Power_Mod powermod_x_p;
Modular_Reducer mod_p;
diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp
index f97f83aa0..289cdcac4 100644
--- a/src/pubkey/gost_3410/gost_3410.cpp
+++ b/src/pubkey/gost_3410/gost_3410.cpp
@@ -14,7 +14,7 @@
namespace Botan {
-MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
+std::vector<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();
@@ -22,7 +22,7 @@ MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
size_t part_size = std::max(x.bytes(), y.bytes());
- MemoryVector<byte> bits(2*part_size);
+ std::vector<byte> bits(2*part_size);
x.binary_encode(&bits[part_size - x.bytes()]);
y.binary_encode(&bits[2*part_size - y.bytes()]);
@@ -34,22 +34,22 @@ MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
std::swap(bits[part_size+i], bits[2*part_size-1-i]);
}
- return DER_Encoder().encode(bits, OCTET_STRING).get_contents();
+ return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked();
}
AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
{
- MemoryVector<byte> params =
+ std::vector<byte> params =
DER_Encoder().start_cons(SEQUENCE)
.encode(OID(domain().get_oid()))
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
return AlgorithmIdentifier(get_oid(), params);
}
GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
OID ecc_param_id;
@@ -58,7 +58,7 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
domain_params = EC_Group(ecc_param_id);
- SecureVector<byte> bits;
+ secure_vector<byte> bits;
BER_Decoder(key_bits).decode(bits, OCTET_STRING);
const size_t part_size = bits.size() / 2;
@@ -83,7 +83,7 @@ namespace {
BigInt decode_le(const byte msg[], size_t msg_len)
{
- SecureVector<byte> msg_le(msg, msg_len);
+ secure_vector<byte> msg_le(msg, msg + msg_len);
for(size_t i = 0; i != msg_le.size() / 2; ++i)
std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
@@ -102,7 +102,7 @@ GOST_3410_Signature_Operation::GOST_3410_Signature_Operation(
{
}
-SecureVector<byte>
+secure_vector<byte>
GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -129,7 +129,7 @@ GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
if(r == 0 || s == 0)
throw Invalid_State("GOST 34.10: r == 0 || s == 0");
- SecureVector<byte> output(2*order.bytes());
+ secure_vector<byte> output(2*order.bytes());
s.binary_encode(&output[output.size() / 2 - s.bytes()]);
r.binary_encode(&output[output.size() - r.bytes()]);
return output;
diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h
index 7b638d7b5..6b1506b10 100644
--- a/src/pubkey/gost_3410/gost_3410.h
+++ b/src/pubkey/gost_3410/gost_3410.h
@@ -35,7 +35,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey
* Construct from X.509 algorithm id and subject public key bits
*/
GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
/**
* Get this keys algorithm name.
@@ -45,7 +45,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey
AlgorithmIdentifier algorithm_identifier() const;
- MemoryVector<byte> x509_subject_public_key() const;
+ std::vector<byte> x509_subject_public_key() const;
/**
* Get the maximum number of bits allowed to be fed to this key.
@@ -73,7 +73,7 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey,
public:
GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
@@ -103,7 +103,7 @@ class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const { return order.bytes(); }
size_t max_input_bits() const { return order.bits(); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp
index 6e75bc276..f044afd03 100644
--- a/src/pubkey/if_algo/if_algo.cpp
+++ b/src/pubkey/if_algo/if_algo.cpp
@@ -18,18 +18,18 @@ AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const
AlgorithmIdentifier::USE_NULL_PARAM);
}
-MemoryVector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const
+std::vector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(n)
.encode(e)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
BER_Decoder(key_bits)
.start_cons(SEQUENCE)
@@ -49,7 +49,7 @@ bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const
return true;
}
-MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const
+secure_vector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
@@ -68,7 +68,7 @@ MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
const AlgorithmIdentifier&,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
BER_Decoder(key_bits)
.start_cons(SEQUENCE)
diff --git a/src/pubkey/if_algo/if_algo.h b/src/pubkey/if_algo/if_algo.h
index b6683d30e..5c95aecd1 100644
--- a/src/pubkey/if_algo/if_algo.h
+++ b/src/pubkey/if_algo/if_algo.h
@@ -22,7 +22,7 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
{
public:
IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) :
n(n), e(e) {}
@@ -31,7 +31,7 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
AlgorithmIdentifier algorithm_identifier() const;
- MemoryVector<byte> x509_subject_public_key() const;
+ std::vector<byte> x509_subject_public_key() const;
/**
* @return public modulus
@@ -67,7 +67,7 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
bool check_key(RandomNumberGenerator& rng, bool) const;
@@ -93,7 +93,7 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
const BigInt& get_d1() const { return d1; }
const BigInt& get_d2() const { return d2; }
- MemoryVector<byte> pkcs8_private_key() const;
+ secure_vector<byte> pkcs8_private_key() const;
protected:
IF_Scheme_PrivateKey() {}
diff --git a/src/pubkey/keypair/keypair.cpp b/src/pubkey/keypair/keypair.cpp
index 857a5328a..a8631062d 100644
--- a/src/pubkey/keypair/keypair.cpp
+++ b/src/pubkey/keypair/keypair.cpp
@@ -29,14 +29,14 @@ bool encryption_consistency_check(RandomNumberGenerator& rng,
if(encryptor.maximum_input_size() == 0)
return true;
- SecureVector<byte> plaintext =
- rng.random_vec(encryptor.maximum_input_size() - 1);
+ std::vector<byte> plaintext =
+ unlock(rng.random_vec(encryptor.maximum_input_size() - 1));
- SecureVector<byte> ciphertext = encryptor.encrypt(plaintext, rng);
+ std::vector<byte> ciphertext = encryptor.encrypt(plaintext, rng);
if(ciphertext == plaintext)
return false;
- SecureVector<byte> decrypted = decryptor.decrypt(ciphertext);
+ std::vector<byte> decrypted = unlock(decryptor.decrypt(ciphertext));
return (plaintext == decrypted);
}
@@ -51,9 +51,9 @@ bool signature_consistency_check(RandomNumberGenerator& rng,
PK_Signer signer(key, padding);
PK_Verifier verifier(key, padding);
- SecureVector<byte> message = rng.random_vec(16);
+ std::vector<byte> message = unlock(rng.random_vec(16));
- SecureVector<byte> signature;
+ std::vector<byte> signature;
try
{
diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp
index 61cf7eb3f..87cf3d038 100644
--- a/src/pubkey/nr/nr.cpp
+++ b/src/pubkey/nr/nr.cpp
@@ -8,11 +8,12 @@
#include <botan/nr.h>
#include <botan/numthry.h>
#include <botan/keypair.h>
+#include <future>
namespace Botan {
NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
{
}
@@ -48,7 +49,7 @@ NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng,
}
NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
{
@@ -79,7 +80,7 @@ NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) :
{
}
-SecureVector<byte>
+secure_vector<byte>
NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -103,7 +104,7 @@ NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
d = mod_q.reduce(k - x * c);
}
- SecureVector<byte> output(2*q.bytes());
+ secure_vector<byte> output(2*q.bytes());
c.binary_encode(&output[output.size() / 2 - c.bytes()]);
d.binary_encode(&output[output.size() - d.bytes()]);
return output;
@@ -118,13 +119,13 @@ NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) :
mod_q = Modular_Reducer(nr.group_q());
}
-SecureVector<byte>
+secure_vector<byte>
NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
{
const BigInt& q = mod_q.get_modulus();
if(msg_len != 2*q.bytes())
- return false;
+ throw Invalid_Argument("NR verification: Invalid signature");
BigInt c(msg, q.bytes());
BigInt d(msg + q.bytes(), q.bytes());
@@ -132,8 +133,11 @@ NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
if(c.is_zero() || c >= q || d >= q)
throw Invalid_Argument("NR verification: Invalid signature");
- BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c));
- return BigInt::encode(mod_q.reduce(c - i));
+ auto future_y_c = std::async(std::launch::async, powermod_y_p, c);
+ BigInt g_d = powermod_g_p(d);
+
+ BigInt i = mod_p.multiply(g_d, future_y_c.get());
+ return BigInt::encode_locked(mod_q.reduce(c - i));
}
}
diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h
index 0d426fb3a..5be336a21 100644
--- a/src/pubkey/nr/nr.h
+++ b/src/pubkey/nr/nr.h
@@ -30,7 +30,7 @@ class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey
size_t max_input_bits() const { return (group_q().bits() - 1); }
NR_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
NR_PublicKey(const DL_Group& group, const BigInt& pub_key);
protected:
@@ -47,7 +47,7 @@ class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
bool check_key(RandomNumberGenerator& rng, bool strong) const;
NR_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng);
NR_PrivateKey(RandomNumberGenerator& rng,
@@ -67,7 +67,7 @@ class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return (q.bits() - 1); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& q;
@@ -90,7 +90,7 @@ class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification
bool with_recovery() const { return true; }
- SecureVector<byte> verify_mr(const byte msg[], size_t msg_len);
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len);
private:
const BigInt& q;
const BigInt& y;
diff --git a/src/pubkey/pk_algs.cpp b/src/pubkey/pk_algs.cpp
index 9b3218ac4..9673199e0 100644
--- a/src/pubkey/pk_algs.cpp
+++ b/src/pubkey/pk_algs.cpp
@@ -47,7 +47,7 @@
namespace Botan {
Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits)
+ const secure_vector<byte>& key_bits)
{
const std::string alg_name = OIDS::lookup(alg_id.oid);
if(alg_name == "")
@@ -98,11 +98,11 @@ Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
return new ECDH_PublicKey(alg_id, key_bits);
#endif
- return 0;
+ return nullptr;
}
Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng)
{
const std::string alg_name = OIDS::lookup(alg_id.oid);
@@ -154,7 +154,7 @@ Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
return new ECDH_PrivateKey(alg_id, key_bits);
#endif
- return 0;
+ return nullptr;
}
}
diff --git a/src/pubkey/pk_algs.h b/src/pubkey/pk_algs.h
index a1e65cb3d..d8f24a1b8 100644
--- a/src/pubkey/pk_algs.h
+++ b/src/pubkey/pk_algs.h
@@ -13,10 +13,10 @@
namespace Botan {
Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits);
+ const secure_vector<byte>& key_bits);
Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng);
}
diff --git a/src/pubkey/pk_keys.h b/src/pubkey/pk_keys.h
index 770949b59..a3b693956 100644
--- a/src/pubkey/pk_keys.h
+++ b/src/pubkey/pk_keys.h
@@ -69,7 +69,7 @@ class BOTAN_DLL Public_Key
/**
* @return X.509 subject key encoding for this key object
*/
- virtual MemoryVector<byte> x509_subject_public_key() const = 0;
+ virtual std::vector<byte> x509_subject_public_key() const = 0;
virtual ~Public_Key() {}
protected:
@@ -89,7 +89,7 @@ class BOTAN_DLL Private_Key : public virtual Public_Key
/**
* @return PKCS #8 private key encoding for this key object
*/
- virtual MemoryVector<byte> pkcs8_private_key() const = 0;
+ virtual secure_vector<byte> pkcs8_private_key() const = 0;
/**
* @return PKCS #8 AlgorithmIdentifier for this key
@@ -121,7 +121,7 @@ class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
/*
* @return public component of this key
*/
- virtual MemoryVector<byte> public_value() const = 0;
+ virtual std::vector<byte> public_value() const = 0;
virtual ~PK_Key_Agreement_Key() {}
};
diff --git a/src/pubkey/pk_ops.h b/src/pubkey/pk_ops.h
index 51543cd33..8a08ef430 100644
--- a/src/pubkey/pk_ops.h
+++ b/src/pubkey/pk_ops.h
@@ -23,7 +23,7 @@ class BOTAN_DLL Encryption
public:
virtual size_t max_input_bits() const = 0;
- virtual SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
+ virtual secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng) = 0;
virtual ~Encryption() {}
@@ -37,7 +37,7 @@ class BOTAN_DLL Decryption
public:
virtual size_t max_input_bits() const = 0;
- virtual SecureVector<byte> decrypt(const byte msg[],
+ virtual secure_vector<byte> decrypt(const byte msg[],
size_t msg_len) = 0;
virtual ~Decryption() {}
@@ -73,7 +73,7 @@ class BOTAN_DLL Signature
* @param msg_len the length of msg in bytes
* @param rng a random number generator
*/
- virtual SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ virtual secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng) = 0;
virtual ~Signature() {}
@@ -130,7 +130,7 @@ class BOTAN_DLL Verification
* @param msg_len the length of msg in bytes
* @returns recovered message
*/
- virtual SecureVector<byte> verify_mr(const byte[],
+ virtual secure_vector<byte> verify_mr(const byte[],
size_t)
{
throw Invalid_State("Message recovery not supported");
@@ -151,7 +151,7 @@ class BOTAN_DLL Key_Agreement
* @param w_len the length of w in bytes
* @returns the agreed key
*/
- virtual SecureVector<byte> agree(const byte w[], size_t w_len) = 0;
+ virtual secure_vector<byte> agree(const byte w[], size_t w_len) = 0;
virtual ~Key_Agreement() {}
};
diff --git a/src/pubkey/pkcs8.cpp b/src/pubkey/pkcs8.cpp
index 16440b648..baf6d1250 100644
--- a/src/pubkey/pkcs8.cpp
+++ b/src/pubkey/pkcs8.cpp
@@ -24,10 +24,10 @@ namespace {
/*
* Get info from an EncryptedPrivateKeyInfo
*/
-SecureVector<byte> PKCS8_extract(DataSource& source,
+secure_vector<byte> PKCS8_extract(DataSource& source,
AlgorithmIdentifier& pbe_alg_id)
{
- SecureVector<byte> key_data;
+ secure_vector<byte> key_data;
BER_Decoder(source)
.start_cons(SEQUENCE)
@@ -41,11 +41,13 @@ SecureVector<byte> PKCS8_extract(DataSource& source,
/*
* PEM decode and/or decrypt a private key
*/
-SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
- AlgorithmIdentifier& pk_alg_id)
+secure_vector<byte> PKCS8_decode(
+ DataSource& source,
+ std::function<std::pair<bool,std::string> ()> get_passphrase,
+ AlgorithmIdentifier& pk_alg_id)
{
AlgorithmIdentifier pbe_alg_id;
- SecureVector<byte> key_data, key;
+ secure_vector<byte> key_data, key;
bool is_encrypted = true;
try {
@@ -69,9 +71,9 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
if(key_data.empty())
throw PKCS8_Exception("No key data found");
}
- catch(Decoding_Error)
+ catch(Decoding_Error& e)
{
- throw Decoding_Error("PKCS #8 private key decoding failed");
+ throw Decoding_Error("PKCS #8 private key decoding failed: " + std::string(e.what()));
}
if(!is_encrypted)
@@ -89,16 +91,14 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
if(is_encrypted)
{
DataSource_Memory params(pbe_alg_id.parameters);
- std::auto_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
+ std::unique_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
- User_Interface::UI_Result result = User_Interface::OK;
- const std::string passphrase =
- ui.get_passphrase("PKCS #8 private key", source.id(), result);
+ std::pair<bool, std::string> pass = get_passphrase();
- if(result == User_Interface::CANCEL_ACTION)
+ if(pass.first == false)
break;
- pbe->set_key(passphrase);
+ pbe->set_key(pass.second);
Pipe decryptor(pbe.release());
decryptor.process_msg(key_data);
@@ -131,7 +131,7 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
/*
* BER encode a PKCS #8 private key, unencrypted
*/
-SecureVector<byte> BER_encode(const Private_Key& key)
+secure_vector<byte> BER_encode(const Private_Key& key)
{
const size_t PKCS8_VERSION = 0;
@@ -155,14 +155,14 @@ std::string PEM_encode(const Private_Key& key)
/*
* BER encode a PKCS #8 private key, encrypted
*/
-SecureVector<byte> BER_encode(const Private_Key& key,
+secure_vector<byte> BER_encode(const Private_Key& key,
RandomNumberGenerator& rng,
const std::string& pass,
const std::string& pbe_algo)
{
const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-256/CBC)";
- std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
+ std::unique_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
pbe->new_params(rng);
pbe->set_key(pass);
@@ -200,10 +200,10 @@ std::string PEM_encode(const Private_Key& key,
*/
Private_Key* load_key(DataSource& source,
RandomNumberGenerator& rng,
- const User_Interface& ui)
+ std::function<std::pair<bool, std::string> ()> get_pass)
{
AlgorithmIdentifier alg_id;
- SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
+ secure_vector<byte> pkcs8_key = PKCS8_decode(source, get_pass, alg_id);
const std::string alg_name = OIDS::lookup(alg_id.oid);
if(alg_name == "" || alg_name == alg_id.oid.as_string())
@@ -218,12 +218,38 @@ Private_Key* load_key(DataSource& source,
*/
Private_Key* load_key(const std::string& fsname,
RandomNumberGenerator& rng,
- const User_Interface& ui)
+ std::function<std::pair<bool, std::string> ()> get_pass)
{
DataSource_Stream source(fsname, true);
- return PKCS8::load_key(source, rng, ui);
+ return PKCS8::load_key(source, rng, get_pass);
}
+namespace {
+
+class Single_Shot_Passphrase
+ {
+ public:
+ Single_Shot_Passphrase(const std::string& pass) :
+ passphrase(pass), first(true) {}
+
+ std::pair<bool, std::string> operator()()
+ {
+ if(first)
+ {
+ first = false;
+ return std::make_pair(true, passphrase);
+ }
+ else
+ return std::make_pair(false, "");
+ }
+
+ private:
+ std::string passphrase;
+ bool first;
+ };
+
+}
+
/*
* Extract a private key and return it
*/
@@ -231,7 +257,7 @@ Private_Key* load_key(DataSource& source,
RandomNumberGenerator& rng,
const std::string& pass)
{
- return PKCS8::load_key(source, rng, User_Interface(pass));
+ return PKCS8::load_key(source, rng, Single_Shot_Passphrase(pass));
}
/*
@@ -241,7 +267,7 @@ Private_Key* load_key(const std::string& fsname,
RandomNumberGenerator& rng,
const std::string& pass)
{
- return PKCS8::load_key(fsname, rng, User_Interface(pass));
+ return PKCS8::load_key(fsname, rng, Single_Shot_Passphrase(pass));
}
/*
diff --git a/src/pubkey/pkcs8.h b/src/pubkey/pkcs8.h
index 00607b329..fae1633a8 100644
--- a/src/pubkey/pkcs8.h
+++ b/src/pubkey/pkcs8.h
@@ -9,7 +9,7 @@
#define BOTAN_PKCS8_H__
#include <botan/x509_key.h>
-#include <botan/ui.h>
+#include <functional>
namespace Botan {
@@ -32,7 +32,7 @@ namespace PKCS8 {
* @param key the private key to encode
* @return BER encoded key
*/
-BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key);
+BOTAN_DLL secure_vector<byte> BER_encode(const Private_Key& key);
/**
* Get a string containing a PEM encoded private key.
@@ -51,7 +51,7 @@ BOTAN_DLL std::string PEM_encode(const Private_Key& key);
default will be chosen.
* @return encrypted key in binary BER form
*/
-BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key,
+BOTAN_DLL secure_vector<byte> BER_encode(const Private_Key& key,
RandomNumberGenerator& rng,
const std::string& pass,
const std::string& pbe_algo = "");
@@ -123,18 +123,19 @@ inline void encrypt_key(const Private_Key& key,
* Load a key from a data source.
* @param source the data source providing the encoded key
* @param rng the rng to use
-* @param ui the user interface to be used for passphrase dialog
+* @param get_passphrase a function that returns passphrases
* @return loaded private key object
*/
-BOTAN_DLL Private_Key* load_key(DataSource& source,
- RandomNumberGenerator& rng,
- const User_Interface& ui);
+BOTAN_DLL Private_Key* load_key(
+ DataSource& source,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_passphrase);
/** Load a key from a data source.
* @param source the data source providing the encoded key
* @param rng the rng to use
* @param pass the passphrase to decrypt the key. Provide an empty
-* string if the key is not encoded.
+* string if the key is not encrypted
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(DataSource& source,
@@ -145,18 +146,19 @@ BOTAN_DLL Private_Key* load_key(DataSource& source,
* Load a key from a file.
* @param filename the path to the file containing the encoded key
* @param rng the rng to use
-* @param ui the user interface to be used for passphrase dialog
+* @param get_passphrase a function that returns passphrases
* @return loaded private key object
*/
-BOTAN_DLL Private_Key* load_key(const std::string& filename,
- RandomNumberGenerator& rng,
- const User_Interface& ui);
+BOTAN_DLL Private_Key* load_key(
+ const std::string& filename,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_passphrase);
/** Load a key from a file.
* @param filename the path to the file containing the encoded key
* @param rng the rng to use
* @param pass the passphrase to decrypt the key. Provide an empty
-* string if the key is not encoded.
+* string if the key is not encrypted
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(const std::string& filename,
diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp
index 6e63f9fc9..c27cf4a05 100644
--- a/src/pubkey/pubkey.cpp
+++ b/src/pubkey/pubkey.cpp
@@ -38,33 +38,33 @@ PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
throw Lookup_Error("PK_Encryptor_EME: No working engine for " +
key.algo_name());
- eme = (eme_name == "Raw") ? 0 : get_eme(eme_name);
+ eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name);
}
/*
* Encrypt a message
*/
-SecureVector<byte>
+std::vector<byte>
PK_Encryptor_EME::enc(const byte in[],
size_t length,
RandomNumberGenerator& rng) const
{
if(eme)
{
- SecureVector<byte> encoded =
+ secure_vector<byte> encoded =
eme->encode(in, length, op->max_input_bits(), rng);
if(8*(encoded.size() - 1) + high_bit(encoded[0]) > op->max_input_bits())
throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
- return op->encrypt(&encoded[0], encoded.size(), rng);
+ return unlock(op->encrypt(&encoded[0], encoded.size(), rng));
}
else
{
if(8*(length - 1) + high_bit(in[0]) > op->max_input_bits())
throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
- return op->encrypt(&in[0], length, rng);
+ return unlock(op->encrypt(&in[0], length, rng));
}
}
@@ -98,17 +98,17 @@ PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
throw Lookup_Error("PK_Decryptor_EME: No working engine for " +
key.algo_name());
- eme = (eme_name == "Raw") ? 0 : get_eme(eme_name);
+ eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name);
}
/*
* Decrypt a message
*/
-SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[],
- size_t length) const
+secure_vector<byte> PK_Decryptor_EME::dec(const byte msg[],
+ size_t length) const
{
try {
- SecureVector<byte> decrypted = op->decrypt(msg, length);
+ secure_vector<byte> decrypted = op->decrypt(msg, length);
if(eme)
return eme->decode(decrypted, op->max_input_bits());
else
@@ -130,8 +130,8 @@ PK_Signer::PK_Signer(const Private_Key& key,
{
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
- op = 0;
- verify_op = 0;
+ op = nullptr;
+ verify_op = nullptr;
while(const Engine* engine = i.next())
{
@@ -156,7 +156,7 @@ PK_Signer::PK_Signer(const Private_Key& key,
/*
* Sign a message
*/
-SecureVector<byte> PK_Signer::sign_message(const byte msg[], size_t length,
+std::vector<byte> PK_Signer::sign_message(const byte msg[], size_t length,
RandomNumberGenerator& rng)
{
update(msg, length);
@@ -174,16 +174,16 @@ void PK_Signer::update(const byte in[], size_t length)
/*
* Check the signature we just created, to help prevent fault attacks
*/
-bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg,
- const MemoryRegion<byte>& sig) const
+bool PK_Signer::self_test_signature(const std::vector<byte>& msg,
+ const std::vector<byte>& sig) const
{
if(!verify_op)
return true; // checking disabled, assume ok
if(verify_op->with_recovery())
{
- SecureVector<byte> recovered =
- verify_op->verify_mr(&sig[0], sig.size());
+ std::vector<byte> recovered =
+ unlock(verify_op->verify_mr(&sig[0], sig.size()));
if(msg.size() > recovered.size())
{
@@ -206,13 +206,13 @@ bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg,
/*
* Create a signature
*/
-SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
+std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
{
- SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(),
- op->max_input_bits(),
- rng);
+ std::vector<byte> encoded = unlock(emsa->encoding_of(emsa->raw_data(),
+ op->max_input_bits(),
+ rng));
- SecureVector<byte> plain_sig = op->sign(&encoded[0], encoded.size(), rng);
+ std::vector<byte> plain_sig = unlock(op->sign(&encoded[0], encoded.size(), rng));
BOTAN_ASSERT(self_test_signature(encoded, plain_sig),
"PK_Signer consistency check failed");
@@ -234,11 +234,11 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
.start_cons(SEQUENCE)
.encode_list(sig_parts)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
else
throw Encoding_Error("PK_Signer: Unknown signature format " +
- to_string(sig_format));
+ std::to_string(sig_format));
}
/*
@@ -307,7 +307,7 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length)
BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
size_t count = 0;
- SecureVector<byte> real_sig;
+ std::vector<byte> real_sig;
while(ber_sig.more_items())
{
BigInt sig_part;
@@ -324,7 +324,7 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length)
}
else
throw Decoding_Error("PK_Verifier: Unknown signature format " +
- to_string(sig_format));
+ std::to_string(sig_format));
}
catch(Invalid_Argument) { return false; }
}
@@ -332,19 +332,19 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length)
/*
* Verify a signature
*/
-bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg,
+bool PK_Verifier::validate_signature(const secure_vector<byte>& msg,
const byte sig[], size_t sig_len)
{
if(op->with_recovery())
{
- SecureVector<byte> output_of_key = op->verify_mr(sig, sig_len);
+ secure_vector<byte> output_of_key = op->verify_mr(sig, sig_len);
return emsa->verify(output_of_key, msg, op->max_input_bits());
}
else
{
Null_RNG rng;
- SecureVector<byte> encoded =
+ secure_vector<byte> encoded =
emsa->encoding_of(msg, op->max_input_bits(), rng);
return op->verify(&encoded[0], encoded.size(), sig, sig_len);
@@ -370,14 +370,14 @@ PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key,
throw Lookup_Error("PK_Key_Agreement: No working engine for " +
key.algo_name());
- kdf = (kdf_name == "Raw") ? 0 : get_kdf(kdf_name);
+ kdf = (kdf_name == "Raw") ? nullptr : get_kdf(kdf_name);
}
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const byte in[],
size_t in_len, const byte params[],
size_t params_len) const
{
- SecureVector<byte> z = op->agree(in, in_len);
+ secure_vector<byte> z = op->agree(in, in_len);
if(!kdf)
return z;
diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h
index cd813dc65..5013a1ed1 100644
--- a/src/pubkey/pubkey.h
+++ b/src/pubkey/pubkey.h
@@ -45,7 +45,7 @@ class BOTAN_DLL PK_Encryptor
* @param rng the random number source to use
* @return encrypted message
*/
- SecureVector<byte> encrypt(const byte in[], size_t length,
+ std::vector<byte> encrypt(const byte in[], size_t length,
RandomNumberGenerator& rng) const
{
return enc(in, length, rng);
@@ -57,8 +57,9 @@ class BOTAN_DLL PK_Encryptor
* @param rng the random number source to use
* @return encrypted message
*/
- SecureVector<byte> encrypt(const MemoryRegion<byte>& in,
- RandomNumberGenerator& rng) const
+ template<typename Alloc>
+ std::vector<byte> encrypt(const std::vector<byte, Alloc>& in,
+ RandomNumberGenerator& rng) const
{
return enc(&in[0], in.size(), rng);
}
@@ -75,7 +76,7 @@ class BOTAN_DLL PK_Encryptor
PK_Encryptor(const PK_Encryptor&) {}
PK_Encryptor& operator=(const PK_Encryptor&) { return *this; }
- virtual SecureVector<byte> enc(const byte[], size_t,
+ virtual std::vector<byte> enc(const byte[], size_t,
RandomNumberGenerator&) const = 0;
};
@@ -91,7 +92,7 @@ class BOTAN_DLL PK_Decryptor
* @param length the length of the above byte array
* @return decrypted message
*/
- SecureVector<byte> decrypt(const byte in[], size_t length) const
+ secure_vector<byte> decrypt(const byte in[], size_t length) const
{
return dec(in, length);
}
@@ -101,7 +102,8 @@ class BOTAN_DLL PK_Decryptor
* @param in the ciphertext
* @return decrypted message
*/
- SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const
+ template<typename Alloc>
+ secure_vector<byte> decrypt(const std::vector<byte, Alloc>& in) const
{
return dec(&in[0], in.size());
}
@@ -112,7 +114,7 @@ class BOTAN_DLL PK_Decryptor
PK_Decryptor(const PK_Decryptor&) {}
PK_Decryptor& operator=(const PK_Decryptor&) { return *this; }
- virtual SecureVector<byte> dec(const byte[], size_t) const = 0;
+ virtual secure_vector<byte> dec(const byte[], size_t) const = 0;
};
/**
@@ -130,7 +132,7 @@ class BOTAN_DLL PK_Signer
* @param rng the rng to use
* @return signature
*/
- SecureVector<byte> sign_message(const byte in[], size_t length,
+ std::vector<byte> sign_message(const byte in[], size_t length,
RandomNumberGenerator& rng);
/**
@@ -139,8 +141,12 @@ class BOTAN_DLL PK_Signer
* @param rng the rng to use
* @return signature
*/
- SecureVector<byte> sign_message(const MemoryRegion<byte>& in,
- RandomNumberGenerator& rng)
+ std::vector<byte> sign_message(const std::vector<byte>& in,
+ RandomNumberGenerator& rng)
+ { return sign_message(&in[0], in.size(), rng); }
+
+ std::vector<byte> sign_message(const secure_vector<byte>& in,
+ RandomNumberGenerator& rng)
{ return sign_message(&in[0], in.size(), rng); }
/**
@@ -160,7 +166,7 @@ class BOTAN_DLL PK_Signer
* Add a message part.
* @param in the message part to add
*/
- void update(const MemoryRegion<byte>& in) { update(&in[0], in.size()); }
+ void update(const std::vector<byte>& in) { update(&in[0], in.size()); }
/**
* Get the signature of the so far processed message (provided by the
@@ -168,7 +174,7 @@ class BOTAN_DLL PK_Signer
* @param rng the rng to use
* @return signature of the total message
*/
- SecureVector<byte> signature(RandomNumberGenerator& rng);
+ std::vector<byte> signature(RandomNumberGenerator& rng);
/**
* Set the output format of the signature.
@@ -191,8 +197,8 @@ class BOTAN_DLL PK_Signer
~PK_Signer() { delete op; delete verify_op; delete emsa; }
private:
- bool self_test_signature(const MemoryRegion<byte>& msg,
- const MemoryRegion<byte>& sig) const;
+ bool self_test_signature(const std::vector<byte>& msg,
+ const std::vector<byte>& sig) const;
PK_Signer(const PK_Signer&) {}
PK_Signer& operator=(const PK_Signer&) { return *this; }
@@ -227,8 +233,9 @@ class BOTAN_DLL PK_Verifier
* @param sig the signature
* @return true if the signature is valid
*/
- bool verify_message(const MemoryRegion<byte>& msg,
- const MemoryRegion<byte>& sig)
+ template<typename Alloc, typename Alloc2>
+ bool verify_message(const std::vector<byte, Alloc>& msg,
+ const std::vector<byte, Alloc2>& sig)
{
return verify_message(&msg[0], msg.size(),
&sig[0], sig.size());
@@ -254,7 +261,7 @@ class BOTAN_DLL PK_Verifier
* signature to be verified.
* @param in the new message part
*/
- void update(const MemoryRegion<byte>& in)
+ void update(const std::vector<byte>& in)
{ update(&in[0], in.size()); }
/**
@@ -272,7 +279,8 @@ class BOTAN_DLL PK_Verifier
* @param sig the signature to be verified
* @return true if the signature is valid, false otherwise
*/
- bool check_signature(const MemoryRegion<byte>& sig)
+ template<typename Alloc>
+ bool check_signature(const std::vector<byte, Alloc>& sig)
{
return check_signature(&sig[0], sig.size());
}
@@ -298,7 +306,7 @@ class BOTAN_DLL PK_Verifier
PK_Verifier(const PK_Verifier&) {}
PK_Verifier& operator=(const PK_Verifier&) { return *this; }
- bool validate_signature(const MemoryRegion<byte>& msg,
+ bool validate_signature(const secure_vector<byte>& msg,
const byte sig[], size_t sig_len);
PK_Ops::Verification* op;
@@ -336,7 +344,7 @@ class BOTAN_DLL PK_Key_Agreement
* @param params_len the length of params in bytes
*/
SymmetricKey derive_key(size_t key_len,
- const MemoryRegion<byte>& in,
+ const std::vector<byte>& in,
const byte params[],
size_t params_len) const
{
@@ -367,7 +375,7 @@ class BOTAN_DLL PK_Key_Agreement
* @param params extra derivation params
*/
SymmetricKey derive_key(size_t key_len,
- const MemoryRegion<byte>& in,
+ const std::vector<byte>& in,
const std::string& params = "") const
{
return derive_key(key_len, &in[0], in.size(),
@@ -410,7 +418,7 @@ class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor
~PK_Encryptor_EME() { delete op; delete eme; }
private:
- SecureVector<byte> enc(const byte[], size_t,
+ std::vector<byte> enc(const byte[], size_t,
RandomNumberGenerator& rng) const;
PK_Ops::Encryption* op;
@@ -433,7 +441,7 @@ class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor
~PK_Decryptor_EME() { delete op; delete eme; }
private:
- SecureVector<byte> dec(const byte[], size_t) const;
+ secure_vector<byte> dec(const byte[], size_t) const;
PK_Ops::Decryption* op;
const EME* eme;
diff --git a/src/pubkey/rsa/rsa.cpp b/src/pubkey/rsa/rsa.cpp
index 40c3968af..22474d7d5 100644
--- a/src/pubkey/rsa/rsa.cpp
+++ b/src/pubkey/rsa/rsa.cpp
@@ -11,6 +11,7 @@
#include <botan/numthry.h>
#include <botan/keypair.h>
#include <botan/internal/assert.h>
+#include <future>
namespace Botan {
@@ -22,7 +23,7 @@ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
{
if(bits < 512)
throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
- to_string(bits) + " bits long");
+ std::to_string(bits) + " bits long");
if(exp < 3 || exp % 2 == 0)
throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
@@ -78,15 +79,16 @@ BigInt RSA_Private_Operation::private_op(const BigInt& m) const
if(m >= n)
throw Invalid_Argument("RSA private op - input is too large");
- BigInt j1 = powermod_d1_p(m);
+ auto future_j1 = std::async(std::launch::async, powermod_d1_p, m);
BigInt j2 = powermod_d2_q(m);
+ BigInt j1 = future_j1.get();
j1 = mod_p.reduce(sub_mul(j1, j2, c));
return mul_add(j1, q, j2);
}
-SecureVector<byte>
+secure_vector<byte>
RSA_Private_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
@@ -103,7 +105,7 @@ RSA_Private_Operation::sign(const byte msg[], size_t msg_len,
/*
* RSA Decryption Operation
*/
-SecureVector<byte>
+secure_vector<byte>
RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
@@ -112,7 +114,7 @@ RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len)
BOTAN_ASSERT(m == powermod_e_n(x),
"RSA private op failed consistency check");
- return BigInt::encode(x);
+ return BigInt::encode_locked(x);
}
}
diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h
index dddecdbed..0942d92ad 100644
--- a/src/pubkey/rsa/rsa.h
+++ b/src/pubkey/rsa/rsa.h
@@ -24,7 +24,7 @@ class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey
std::string algo_name() const { return "RSA"; }
RSA_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
IF_Scheme_PublicKey(alg_id, key_bits)
{}
@@ -51,7 +51,7 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
bool check_key(RandomNumberGenerator& rng, bool) const;
RSA_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
@@ -94,10 +94,10 @@ class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature,
size_t max_input_bits() const { return (n.bits() - 1); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
- SecureVector<byte> decrypt(const byte msg[], size_t msg_len);
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len);
private:
BigInt private_op(const BigInt& m) const;
@@ -124,17 +124,17 @@ class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification,
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
- SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
return BigInt::encode_1363(public_op(m), n.bytes());
}
- SecureVector<byte> verify_mr(const byte msg[], size_t msg_len)
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
- return BigInt::encode(public_op(m));
+ return BigInt::encode_locked(public_op(m));
}
private:
diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp
index 5f58d8e88..d57b967e9 100644
--- a/src/pubkey/rw/rw.cpp
+++ b/src/pubkey/rw/rw.cpp
@@ -10,6 +10,7 @@
#include <botan/keypair.h>
#include <botan/parsing.h>
#include <algorithm>
+#include <future>
namespace Botan {
@@ -21,7 +22,7 @@ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng,
{
if(bits < 512)
throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
- to_string(bits) + " bits long");
+ std::to_string(bits) + " bits long");
if(exp < 2 || exp % 2 == 1)
throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
@@ -70,7 +71,7 @@ RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) :
{
}
-SecureVector<byte>
+secure_vector<byte>
RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng)
{
@@ -90,18 +91,18 @@ RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
i = blinder.blind(i);
- BigInt j1 = powermod_d1_p(i);
- BigInt j2 = powermod_d2_q(i);
- j1 = mod_p.reduce(sub_mul(j1, j2, c));
+ auto future_j1 = std::async(std::launch::async, powermod_d1_p, i);
+ const BigInt j2 = powermod_d2_q(i);
+ BigInt j1 = future_j1.get();
- BigInt r = blinder.unblind(mul_add(j1, q, j2));
+ j1 = mod_p.reduce(sub_mul(j1, j2, c));
- r = std::min(r, n - r);
+ const BigInt r = blinder.unblind(mul_add(j1, q, j2));
- return BigInt::encode_1363(r, n.bytes());
+ return BigInt::encode_1363(std::min(r, n - r), n.bytes());
}
-SecureVector<byte>
+secure_vector<byte>
RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
@@ -111,15 +112,15 @@ RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
BigInt r = powermod_e_n(m);
if(r % 16 == 12)
- return BigInt::encode(r);
+ return BigInt::encode_locked(r);
if(r % 8 == 6)
- return BigInt::encode(2*r);
+ return BigInt::encode_locked(2*r);
r = n - r;
if(r % 16 == 12)
- return BigInt::encode(r);
+ return BigInt::encode_locked(r);
if(r % 8 == 6)
- return BigInt::encode(2*r);
+ return BigInt::encode_locked(2*r);
throw Invalid_Argument("RW signature verification: Invalid signature");
}
diff --git a/src/pubkey/rw/rw.h b/src/pubkey/rw/rw.h
index b8d92eb3a..1e918e70c 100644
--- a/src/pubkey/rw/rw.h
+++ b/src/pubkey/rw/rw.h
@@ -24,7 +24,7 @@ class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey
std::string algo_name() const { return "RW"; }
RW_PublicKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits) :
+ const secure_vector<byte>& key_bits) :
IF_Scheme_PublicKey(alg_id, key_bits)
{}
@@ -44,7 +44,7 @@ class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
{
public:
RW_PrivateKey(const AlgorithmIdentifier& alg_id,
- const MemoryRegion<byte>& key_bits,
+ const secure_vector<byte>& key_bits,
RandomNumberGenerator& rng) :
IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
@@ -69,7 +69,7 @@ class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature
size_t max_input_bits() const { return (n.bits() - 1); }
- SecureVector<byte> sign(const byte msg[], size_t msg_len,
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& n;
@@ -95,7 +95,7 @@ class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
- SecureVector<byte> verify_mr(const byte msg[], size_t msg_len);
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len);
private:
const BigInt& n;
diff --git a/src/pubkey/workfactor.cpp b/src/pubkey/workfactor.cpp
index f3d5d164a..72ba75cf9 100644
--- a/src/pubkey/workfactor.cpp
+++ b/src/pubkey/workfactor.cpp
@@ -1,6 +1,6 @@
/*
* Public Key Work Factor Functions
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,39 +11,40 @@
namespace Botan {
-/*
-* Choose the exponent size for a DL group
-*/
size_t dl_work_factor(size_t bits)
{
-#if 0
/*
- These values were taken from RFC 3526
+ Based on GNFS work factors. Constant is 1.43 times the asymptotic
+ value; I'm not sure but I believe that came from a paper on 'real
+ world' runtimes, but I don't remember where now.
+
+ Sample return values:
+ |512| -> 64
+ |1024| -> 86
+ |1536| -> 102
+ |2048| -> 116
+ |3072| -> 138
+ |4096| -> 155
+ |8192| -> 206
+
+ For DL algos, we use an exponent of twice the size of the result;
+ the assumption is that an arbitrary discrete log on a group of size
+ bits would take about 2^n effort, and thus using an exponent of
+ size 2^(2*n) implies that all available attacks are about as easy
+ (as e.g Pollard's kangaroo algorithm can compute the DL in sqrt(x)
+ operations) while minimizing the exponent size for performance
+ reasons.
*/
- if(bits <= 1536)
- return 90;
- else if(bits <= 2048)
- return 110;
- else if(bits <= 3072)
- return 130;
- else if(bits <= 4096)
- return 150;
- else if(bits <= 6144)
- return 170;
- else if(bits <= 8192)
- return 190;
- return 256;
-#else
- const double MIN_ESTIMATE = 64;
-
- const double log_x = bits / 1.44;
+
+ const size_t MIN_WORKFACTOR = 64;
+
+ // approximates natural logarithm of p
+ const double log_p = bits / 1.4426;
const double strength =
- 2.76 * std::pow(log_x, 1.0/3.0) * std::pow(std::log(log_x), 2.0/3.0);
+ 2.76 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0);
- return static_cast<size_t>(std::max(strength, MIN_ESTIMATE));
-#endif
+ return std::max(static_cast<size_t>(strength), MIN_WORKFACTOR);
}
-
}
diff --git a/src/pubkey/workfactor.h b/src/pubkey/workfactor.h
index bd1a43298..179b580e7 100644
--- a/src/pubkey/workfactor.h
+++ b/src/pubkey/workfactor.h
@@ -13,7 +13,7 @@
namespace Botan {
/**
-* Estimate work factor
+* Estimate work factor for discrete logarithm
* @param prime_group_size size of the group in bits
* @return estimated security level for this group
*/
diff --git a/src/pubkey/x509_key.cpp b/src/pubkey/x509_key.cpp
index c55f37d94..797ec273c 100644
--- a/src/pubkey/x509_key.cpp
+++ b/src/pubkey/x509_key.cpp
@@ -18,14 +18,14 @@ namespace Botan {
namespace X509 {
-MemoryVector<byte> BER_encode(const Public_Key& key)
+std::vector<byte> BER_encode(const Public_Key& key)
{
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(key.algorithm_identifier())
.encode(key.x509_subject_public_key(), BIT_STRING)
.end_cons()
- .get_contents();
+ .get_contents_unlocked();
}
/*
@@ -44,7 +44,7 @@ Public_Key* load_key(DataSource& source)
{
try {
AlgorithmIdentifier alg_id;
- MemoryVector<byte> key_bits;
+ secure_vector<byte> key_bits;
if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
{
@@ -92,7 +92,7 @@ Public_Key* load_key(const std::string& fsname)
/*
* Extract a public key and return it
*/
-Public_Key* load_key(const MemoryRegion<byte>& mem)
+Public_Key* load_key(const secure_vector<byte>& mem)
{
DataSource_Memory source(mem);
return X509::load_key(source);
diff --git a/src/pubkey/x509_key.h b/src/pubkey/x509_key.h
index 13ad7e635..fde765715 100644
--- a/src/pubkey/x509_key.h
+++ b/src/pubkey/x509_key.h
@@ -30,7 +30,7 @@ namespace X509 {
* @param key the public key to encode
* @return BER encoding of this key
*/
-BOTAN_DLL MemoryVector<byte> BER_encode(const Public_Key& key);
+BOTAN_DLL std::vector<byte> BER_encode(const Public_Key& key);
/**
* PEM encode a public key into a string.
@@ -58,7 +58,7 @@ BOTAN_DLL Public_Key* load_key(const std::string& filename);
* @param enc the memory region containing the DER or PEM encoded key
* @return new public key object
*/
-BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
+BOTAN_DLL Public_Key* load_key(const secure_vector<byte>& enc);
/**
* Copy a key.
diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp
index 74ba522a4..da7535b18 100644
--- a/src/rng/hmac_rng/hmac_rng.cpp
+++ b/src/rng/hmac_rng/hmac_rng.cpp
@@ -8,7 +8,6 @@
#include <botan/hmac_rng.h>
#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
-#include <botan/internal/stl_util.h>
#include <algorithm>
namespace Botan {
@@ -16,7 +15,7 @@ namespace Botan {
namespace {
void hmac_prf(MessageAuthenticationCode* prf,
- MemoryRegion<byte>& K,
+ secure_vector<byte>& K,
u32bit& counter,
const std::string& label)
{
@@ -124,7 +123,7 @@ void HMAC_RNG::reseed(size_t poll_bits)
*/
void HMAC_RNG::add_entropy(const byte input[], size_t length)
{
- const size_t USER_ENTROPY_WATERSHED = 20;
+ const size_t USER_ENTROPY_WATERSHED = 64;
extractor->update(input, length);
user_input_len += length;
@@ -136,7 +135,7 @@ void HMAC_RNG::add_entropy(const byte input[], size_t length)
* the extractor input.
*/
if(user_input_len >= USER_ENTROPY_WATERSHED)
- reseed(128);
+ reseed(0);
}
/*
@@ -201,7 +200,7 @@ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
the estimated entropy counter is high enough. That variable is only
set when a reseeding is performed.
*/
- MemoryVector<byte> prf_key(extractor->output_length());
+ secure_vector<byte> prf_key(extractor->output_length());
prf->set_key(prf_key);
/*
@@ -224,8 +223,8 @@ HMAC_RNG::~HMAC_RNG()
delete extractor;
delete prf;
- std::for_each(entropy_sources.begin(), entropy_sources.end(),
- del_fun<EntropySource>());
+ for(auto src : entropy_sources)
+ delete src;
counter = 0;
}
diff --git a/src/rng/hmac_rng/hmac_rng.h b/src/rng/hmac_rng/hmac_rng.h
index fc6a14f3a..1e70c00a7 100644
--- a/src/rng/hmac_rng/hmac_rng.h
+++ b/src/rng/hmac_rng/hmac_rng.h
@@ -51,7 +51,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
std::vector<EntropySource*> entropy_sources;
bool seeded;
- SecureVector<byte> K, io_buffer;
+ secure_vector<byte> K, io_buffer;
size_t user_input_len;
u32bit counter;
};
diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp
index 92f225a9c..ef55f3975 100644
--- a/src/rng/randpool/randpool.cpp
+++ b/src/rng/randpool/randpool.cpp
@@ -8,8 +8,8 @@
#include <botan/randpool.h>
#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
-#include <botan/internal/stl_util.h>
#include <algorithm>
+#include <chrono>
namespace Botan {
@@ -56,7 +56,7 @@ void Randpool::update_buffer()
mac->update(static_cast<byte>(GEN_OUTPUT));
mac->update(counter);
- SecureVector<byte> mac_val = mac->final();
+ secure_vector<byte> mac_val = mac->final();
for(size_t i = 0; i != mac_val.size(); ++i)
buffer[i % buffer.size()] ^= mac_val[i];
@@ -112,7 +112,7 @@ void Randpool::reseed(size_t poll_bits)
}
}
- SecureVector<byte> mac_val = mac->final();
+ secure_vector<byte> mac_val = mac->final();
xor_buf(pool, mac_val, mac_val.size());
mix_pool();
@@ -126,7 +126,7 @@ void Randpool::reseed(size_t poll_bits)
*/
void Randpool::add_entropy(const byte input[], size_t length)
{
- SecureVector<byte> mac_val = mac->process(input, length);
+ secure_vector<byte> mac_val = mac->process(input, length);
xor_buf(pool, mac_val, mac_val.size());
mix_pool();
@@ -202,8 +202,8 @@ Randpool::~Randpool()
delete cipher;
delete mac;
- std::for_each(entropy_sources.begin(), entropy_sources.end(),
- del_fun<EntropySource>());
+ for(auto i = entropy_sources.begin(); i != entropy_sources.end(); ++i)
+ delete *i;
}
}
diff --git a/src/rng/randpool/randpool.h b/src/rng/randpool/randpool.h
index ed224221c..64572bcfb 100644
--- a/src/rng/randpool/randpool.h
+++ b/src/rng/randpool/randpool.h
@@ -52,7 +52,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator
MessageAuthenticationCode* mac;
std::vector<EntropySource*> entropy_sources;
- SecureVector<byte> pool, buffer, counter;
+ secure_vector<byte> pool, buffer, counter;
bool seeded;
};
diff --git a/src/rng/rng.h b/src/rng/rng.h
index c078ef08f..12b423e7c 100644
--- a/src/rng/rng.h
+++ b/src/rng/rng.h
@@ -37,9 +37,9 @@ class BOTAN_DLL RandomNumberGenerator
* @param bytes number of bytes in the result
* @return randomized vector of length bytes
*/
- SecureVector<byte> random_vec(size_t bytes)
+ secure_vector<byte> random_vec(size_t bytes)
{
- SecureVector<byte> output(bytes);
+ secure_vector<byte> output(bytes);
randomize(&output[0], output.size());
return output;
}
diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp
index ac77b4344..7562c7ad5 100644
--- a/src/rng/x931_rng/x931_rng.cpp
+++ b/src/rng/x931_rng/x931_rng.cpp
@@ -40,7 +40,7 @@ void ANSI_X931_RNG::update_buffer()
{
const size_t BLOCK_SIZE = cipher->block_size();
- SecureVector<byte> DT = prng->random_vec(BLOCK_SIZE);
+ secure_vector<byte> DT = prng->random_vec(BLOCK_SIZE);
cipher->encrypt(DT);
xor_buf(&R[0], &V[0], &DT[0], BLOCK_SIZE);
diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h
index 41fa9328b..c8a1b8707 100644
--- a/src/rng/x931_rng/x931_rng.h
+++ b/src/rng/x931_rng/x931_rng.h
@@ -42,7 +42,7 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
BlockCipher* cipher;
RandomNumberGenerator* prng;
- SecureVector<byte> V, R;
+ secure_vector<byte> V, R;
size_t position;
};
diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp
index 0dac31cef..8f4dc70d8 100644
--- a/src/selftest/selftest.cpp
+++ b/src/selftest/selftest.cpp
@@ -125,8 +125,7 @@ namespace {
void verify_results(const std::string& algo,
const std::map<std::string, bool>& results)
{
- for(std::map<std::string, bool>::const_iterator i = results.begin();
- i != results.end(); ++i)
+ for(auto i = results.begin(); i != results.end(); ++i)
{
if(!i->second)
throw Self_Test_Failure(algo + " self-test failed, provider "+
diff --git a/src/ssl/c_kex.cpp b/src/ssl/c_kex.cpp
deleted file mode 100644
index 0f20b819c..000000000
--- a/src/ssl/c_kex.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-* Client Key Exchange Message
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/pubkey.h>
-#include <botan/dh.h>
-#include <botan/rsa.h>
-#include <botan/rng.h>
-#include <botan/loadstor.h>
-#include <memory>
-
-namespace Botan {
-
-/**
-* Create a new Client Key Exchange message
-*/
-Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng,
- Record_Writer& writer,
- HandshakeHash& hash,
- const Public_Key* pub_key,
- Version_Code using_version,
- Version_Code pref_version)
- {
- include_length = true;
-
- if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key))
- {
- DH_PrivateKey priv_key(rng, dh_pub->get_domain());
-
- PK_Key_Agreement ka(priv_key, "Raw");
-
- pre_master = ka.derive_key(0, dh_pub->public_value()).bits_of();
-
- key_material = priv_key.public_value();
- }
- else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key))
- {
- pre_master = rng.random_vec(48);
- pre_master[0] = (pref_version >> 8) & 0xFF;
- pre_master[1] = (pref_version ) & 0xFF;
-
- PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");
-
- key_material = encryptor.encrypt(pre_master, rng);
-
- if(using_version == SSL_V3)
- include_length = false;
- }
- else
- throw Invalid_Argument("Client_Key_Exchange: Key not RSA or DH");
-
- send(writer, hash);
- }
-
-/**
-* Read a Client Key Exchange message
-*/
-Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents,
- const CipherSuite& suite,
- Version_Code using_version)
- {
- include_length = true;
-
- if(using_version == SSL_V3 && (suite.kex_type() == TLS_ALGO_KEYEXCH_RSA))
- include_length = false;
-
- deserialize(contents);
- }
-
-/**
-* Serialize a Client Key Exchange message
-*/
-SecureVector<byte> Client_Key_Exchange::serialize() const
- {
- if(include_length)
- {
- SecureVector<byte> buf;
- append_tls_length_value(buf, key_material, 2);
- return buf;
- }
- else
- return key_material;
- }
-
-/**
-* Deserialize a Client Key Exchange message
-*/
-void Client_Key_Exchange::deserialize(const MemoryRegion<byte>& buf)
- {
- if(include_length)
- {
- TLS_Data_Reader reader(buf);
- key_material = reader.get_range<byte>(2, 0, 65535);
- }
- else
- key_material = buf;
- }
-
-/**
-* Return the pre_master_secret
-*/
-SecureVector<byte>
-Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
- const Private_Key* priv_key,
- Version_Code version)
- {
-
- if(const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key))
- {
- try {
- PK_Key_Agreement ka(*dh_priv, "Raw");
-
- pre_master = ka.derive_key(0, key_material).bits_of();
- }
- catch(...)
- {
- /*
- * Something failed in the DH computation. To avoid possible
- * timing attacks, randomize the pre-master output and carry
- * on, allowing the protocol to fail later in the finished
- * checks.
- */
- pre_master = rng.random_vec(dh_priv->public_value().size());
- }
-
- return pre_master;
- }
- else if(const RSA_PrivateKey* rsa_priv = dynamic_cast<const RSA_PrivateKey*>(priv_key))
- {
- PK_Decryptor_EME decryptor(*rsa_priv, "PKCS1v15");
-
- try {
- pre_master = decryptor.decrypt(key_material);
-
- if(pre_master.size() != 48 ||
- make_u16bit(pre_master[0], pre_master[1]) != version)
- throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
- }
- catch(...)
- {
- pre_master = rng.random_vec(48);
- pre_master[0] = (version >> 8) & 0xFF;
- pre_master[1] = (version ) & 0xFF;
- }
-
- return pre_master;
- }
- else
- throw Invalid_Argument("Client_Key_Exchange: Bad key for decrypt");
- }
-
-/**
-* Return the pre_master_secret
-*/
-SecureVector<byte> Client_Key_Exchange::pre_master_secret() const
- {
- return pre_master;
- }
-
-}
diff --git a/src/ssl/cert_req.cpp b/src/ssl/cert_req.cpp
deleted file mode 100644
index b8b2624bf..000000000
--- a/src/ssl/cert_req.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-* Certificate Request Message
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/loadstor.h>
-#include <botan/secqueue.h>
-
-namespace Botan {
-
-/**
-* Create a new Certificate Request message
-*/
-Certificate_Req::Certificate_Req(Record_Writer& writer,
- HandshakeHash& hash,
- const std::vector<X509_Certificate>& certs)
- {
- for(size_t i = 0; i != certs.size(); ++i)
- names.push_back(certs[i].subject_dn());
-
- // FIXME: should be able to choose what to ask for
- types.push_back(RSA_CERT);
- types.push_back(DSS_CERT);
-
- send(writer, hash);
- }
-
-/**
-* Serialize a Certificate Request message
-*/
-SecureVector<byte> Certificate_Req::serialize() const
- {
- SecureVector<byte> buf;
-
- append_tls_length_value(buf, types, 1);
-
- DER_Encoder encoder;
- for(size_t i = 0; i != names.size(); ++i)
- encoder.encode(names[i]);
-
- append_tls_length_value(buf, encoder.get_contents(), 2);
-
- return buf;
- }
-
-/**
-* Deserialize a Certificate Request message
-*/
-void Certificate_Req::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size() < 4)
- throw Decoding_Error("Certificate_Req: Bad certificate request");
-
- size_t types_size = buf[0];
-
- if(buf.size() < types_size + 3)
- throw Decoding_Error("Certificate_Req: Bad certificate request");
-
- for(size_t i = 0; i != types_size; ++i)
- types.push_back(static_cast<Certificate_Type>(buf[i+1]));
-
- size_t names_size = make_u16bit(buf[types_size+2], buf[types_size+3]);
-
- if(buf.size() != names_size + types_size + 3)
- throw Decoding_Error("Certificate_Req: Bad certificate request");
-
- BER_Decoder decoder(&buf[types_size + 3], names_size);
-
- while(decoder.more_items())
- {
- X509_DN name;
- decoder.decode(name);
- names.push_back(name);
- }
- }
-
-/**
-* Create a new Certificate message
-*/
-Certificate::Certificate(Record_Writer& writer,
- const std::vector<X509_Certificate>& cert_list,
- HandshakeHash& hash)
- {
- certs = cert_list;
- send(writer, hash);
- }
-
-/**
-* Serialize a Certificate message
-*/
-SecureVector<byte> Certificate::serialize() const
- {
- SecureVector<byte> buf(3);
-
- for(size_t i = 0; i != certs.size(); ++i)
- {
- SecureVector<byte> raw_cert = certs[i].BER_encode();
- const size_t cert_size = raw_cert.size();
- for(size_t i = 0; i != 3; ++i)
- buf.push_back(get_byte<u32bit>(i+1, cert_size));
- buf += raw_cert;
- }
-
- const size_t buf_size = buf.size() - 3;
- for(size_t i = 0; i != 3; ++i)
- buf[i] = get_byte<u32bit>(i+1, buf_size);
-
- return buf;
- }
-
-/**
-* Deserialize a Certificate message
-*/
-void Certificate::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size() < 3)
- throw Decoding_Error("Certificate: Message malformed");
-
- const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]);
-
- SecureQueue queue;
- queue.write(&buf[3], buf.size() - 3);
-
- if(queue.size() != total_size)
- throw Decoding_Error("Certificate: Message malformed");
-
- while(queue.size())
- {
- if(queue.size() < 3)
- throw Decoding_Error("Certificate: Message malformed");
-
- byte len[3];
- queue.read(len, 3);
-
- const size_t cert_size = make_u32bit(0, len[0], len[1], len[2]);
- const size_t original_size = queue.size();
-
- X509_Certificate cert(queue);
- if(queue.size() + cert_size != original_size)
- throw Decoding_Error("Certificate: Message malformed");
- certs.push_back(cert);
- }
- }
-
-}
diff --git a/src/ssl/cert_ver.cpp b/src/ssl/cert_ver.cpp
deleted file mode 100644
index 3220a8c9e..000000000
--- a/src/ssl/cert_ver.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-* Certificate Verify Message
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/pubkey.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <botan/loadstor.h>
-#include <memory>
-
-namespace Botan {
-
-/**
-* Create a new Certificate Verify message
-*/
-Certificate_Verify::Certificate_Verify(RandomNumberGenerator& rng,
- Record_Writer& writer,
- HandshakeHash& hash,
- const Private_Key* priv_key)
- {
- std::string padding = "";
- Signature_Format format = IEEE_1363;
-
- if(priv_key->algo_name() == "RSA")
- padding = "EMSA3(TLS.Digest.0)";
- else if(priv_key->algo_name() == "DSA")
- {
- padding == "EMSA1(SHA-1)";
- format = DER_SEQUENCE;
- }
- else
- throw Invalid_Argument(priv_key->algo_name() +
- " is invalid/unknown for TLS signatures");
-
- PK_Signer signer(*priv_key, padding, format);
-
- signature = signer.sign_message(hash.final(), rng);
- send(writer, hash);
- }
-
-/**
-* Serialize a Certificate Verify message
-*/
-SecureVector<byte> Certificate_Verify::serialize() const
- {
- SecureVector<byte> buf;
-
- const u16bit sig_len = signature.size();
- buf.push_back(get_byte(0, sig_len));
- buf.push_back(get_byte(1, sig_len));
- buf += signature;
-
- return buf;
- }
-
-/**
-* Deserialize a Certificate Verify message
-*/
-void Certificate_Verify::deserialize(const MemoryRegion<byte>& buf)
- {
- TLS_Data_Reader reader(buf);
- signature = reader.get_range<byte>(2, 0, 65535);
- }
-
-/**
-* Verify a Certificate Verify message
-*/
-bool Certificate_Verify::verify(const X509_Certificate& cert,
- HandshakeHash& hash)
- {
- // FIXME: duplicate of Server_Key_Exchange::verify
-
- std::auto_ptr<Public_Key> key(cert.subject_public_key());
-
- std::string padding = "";
- Signature_Format format = IEEE_1363;
-
- if(key->algo_name() == "RSA")
- padding = "EMSA3(TLS.Digest.0)";
- else if(key->algo_name() == "DSA")
- {
- padding == "EMSA1(SHA-1)";
- format = DER_SEQUENCE;
- }
- else
- throw Invalid_Argument(key->algo_name() +
- " is invalid/unknown for TLS signatures");
-
- PK_Verifier verifier(*key, padding, format);
- return verifier.verify_message(hash.final(), signature);
- }
-
-}
diff --git a/src/ssl/finished.cpp b/src/ssl/finished.cpp
deleted file mode 100644
index d76fbd884..000000000
--- a/src/ssl/finished.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-* Finished Message
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/prf_tls.h>
-
-namespace Botan {
-
-/**
-* Create a new Finished message
-*/
-Finished::Finished(Record_Writer& writer,
- Version_Code version, Connection_Side side,
- const MemoryRegion<byte>& master_secret,
- HandshakeHash& hash)
- {
- verification_data = compute_verify(master_secret, hash, side, version);
- send(writer, hash);
- }
-
-/**
-* Serialize a Finished message
-*/
-SecureVector<byte> Finished::serialize() const
- {
- return verification_data;
- }
-
-/**
-* Deserialize a Finished message
-*/
-void Finished::deserialize(const MemoryRegion<byte>& buf)
- {
- verification_data = buf;
- }
-
-/**
-* Verify a Finished message
-*/
-bool Finished::verify(const MemoryRegion<byte>& secret, Version_Code version,
- const HandshakeHash& hash, Connection_Side side)
- {
- SecureVector<byte> computed = compute_verify(secret, hash, side, version);
- if(computed == verification_data)
- return true;
- return false;
- }
-
-/**
-* Compute the verify_data
-*/
-SecureVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret,
- HandshakeHash hash,
- Connection_Side side,
- Version_Code version)
- {
- if(version == SSL_V3)
- {
- const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 };
- const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 };
-
- SecureVector<byte> ssl3_finished;
-
- if(side == CLIENT)
- hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL));
- else
- hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL));
-
- return hash.final_ssl3(secret);
- }
- else if(version == TLS_V10 || version == TLS_V11)
- {
- const byte TLS_CLIENT_LABEL[] = {
- 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69,
- 0x73, 0x68, 0x65, 0x64 };
-
- const byte TLS_SERVER_LABEL[] = {
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69,
- 0x73, 0x68, 0x65, 0x64 };
-
- TLS_PRF prf;
-
- SecureVector<byte> input;
- if(side == CLIENT)
- input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL));
- else
- input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL));
- input += hash.final();
-
- return prf.derive_key(12, secret, input);
- }
- else
- throw Invalid_Argument("Finished message: Unknown protocol version");
- }
-
-}
diff --git a/src/ssl/hello.cpp b/src/ssl/hello.cpp
deleted file mode 100644
index ae0d9607b..000000000
--- a/src/ssl/hello.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
-* TLS Hello Messages
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-
-namespace Botan {
-
-/*
-* Encode and send a Handshake message
-*/
-void HandshakeMessage::send(Record_Writer& writer, HandshakeHash& hash) const
- {
- SecureVector<byte> buf = serialize();
- SecureVector<byte> send_buf(4);
-
- const size_t buf_size = buf.size();
-
- send_buf[0] = type();
-
- for(size_t i = 1; i != 4; ++i)
- send_buf[i] = get_byte<u32bit>(i, buf_size);
-
- send_buf += buf;
-
- hash.update(send_buf);
-
- writer.send(HANDSHAKE, &send_buf[0], send_buf.size());
- writer.flush();
- }
-
-/*
-* Create a new Hello Request message
-*/
-Hello_Request::Hello_Request(Record_Writer& writer)
- {
- HandshakeHash dummy; // FIXME: *UGLY*
- send(writer, dummy);
- }
-
-/*
-* Serialize a Hello Request message
-*/
-SecureVector<byte> Hello_Request::serialize() const
- {
- return SecureVector<byte>();
- }
-
-/*
-* Deserialize a Hello Request message
-*/
-void Hello_Request::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Hello_Request: Must be empty, and is not");
- }
-
-/*
-* Create a new Client Hello message
-*/
-Client_Hello::Client_Hello(RandomNumberGenerator& rng,
- Record_Writer& writer,
- const TLS_Policy& policy,
- HandshakeHash& hash)
- {
- c_random = rng.random_vec(32);
-
- suites = policy.ciphersuites();
- comp_algos = policy.compression();
- c_version = policy.pref_version();
-
- send(writer, hash);
- }
-
-/*
-* Serialize a Client Hello message
-*/
-SecureVector<byte> Client_Hello::serialize() const
- {
- SecureVector<byte> buf;
-
- buf.push_back(static_cast<byte>(c_version >> 8));
- buf.push_back(static_cast<byte>(c_version ));
- buf += c_random;
-
- append_tls_length_value(buf, sess_id, 1);
- append_tls_length_value(buf, suites, 2);
- append_tls_length_value(buf, comp_algos, 1);
-
- return buf;
- }
-
-void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf)
- {
- if(buf.size() < 12 || buf[0] != 1)
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
-
- const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]);
- const size_t sess_id_len = make_u16bit(buf[5], buf[6]);
- const size_t challenge_len = make_u16bit(buf[7], buf[8]);
-
- const size_t expected_size =
- (9 + sess_id_len + cipher_spec_len + challenge_len);
-
- if(buf.size() != expected_size)
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
-
- if(sess_id_len != 0 || cipher_spec_len % 3 != 0 ||
- (challenge_len < 16 || challenge_len > 32))
- {
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
- }
-
- for(size_t i = 9; i != 9 + cipher_spec_len; i += 3)
- {
- if(buf[i] != 0) // a SSLv2 cipherspec; ignore it
- continue;
-
- suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
- }
-
- c_version = static_cast<Version_Code>(make_u16bit(buf[1], buf[2]));
-
- c_random.resize(challenge_len);
- copy_mem(&c_random[0], &buf[9+cipher_spec_len+sess_id_len], challenge_len);
- }
-
-/*
-* Deserialize a Client Hello message
-*/
-void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size() == 0)
- throw Decoding_Error("Client_Hello: Packet corrupted");
-
- if(buf.size() < 41)
- throw Decoding_Error("Client_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- c_version = static_cast<Version_Code>(reader.get_u16bit());
- c_random = reader.get_fixed<byte>(32);
-
- sess_id = reader.get_range<byte>(1, 0, 32);
-
- suites = reader.get_range_vector<u16bit>(2, 1, 32767);
-
- comp_algos = reader.get_range_vector<byte>(1, 1, 255);
-
- if(reader.has_remaining())
- {
- const u16bit all_extn_size = reader.get_u16bit();
-
- if(reader.remaining_bytes() != all_extn_size)
- throw Decoding_Error("Client_Hello: Bad extension size");
-
- while(reader.has_remaining())
- {
- const u16bit extension_code = reader.get_u16bit();
- const u16bit extension_size = reader.get_u16bit();
-
- if(extension_code == TLSEXT_SERVER_NAME_INDICATION)
- {
- u16bit name_bytes = reader.get_u16bit();
-
- while(name_bytes)
- {
- byte name_type = reader.get_byte();
- name_bytes--;
-
- if(name_type == 0) // DNS
- {
- std::vector<byte> name =
- reader.get_range_vector<byte>(2, 1, 65535);
-
- requested_hostname.assign(
- reinterpret_cast<const char*>(&name[0]),
- name.size());
-
- name_bytes -= (2 + name.size());
- }
- else
- {
- reader.discard_next(name_bytes);
- name_bytes = 0;
- }
- }
- }
- else if(extension_code == TLSEXT_SRP_IDENTIFIER)
- {
- std::vector<byte> name = reader.get_range_vector<byte>(1, 1, 255);
-
- requested_srp_id.assign(
- reinterpret_cast<char*>(&name[0]),
- name.size());
- }
- else
- {
- reader.discard_next(extension_size);
- }
- }
- }
- }
-
-/*
-* Check if we offered this ciphersuite
-*/
-bool Client_Hello::offered_suite(u16bit ciphersuite) const
- {
- for(size_t i = 0; i != suites.size(); ++i)
- if(suites[i] == ciphersuite)
- return true;
- return false;
- }
-
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(RandomNumberGenerator& rng,
- Record_Writer& writer,
- const TLS_Policy& policy,
- const std::vector<X509_Certificate>& certs,
- const Client_Hello& c_hello,
- Version_Code ver,
- HandshakeHash& hash)
- {
- bool have_rsa = false, have_dsa = false;
-
- for(size_t i = 0; i != certs.size(); ++i)
- {
- Public_Key* key = certs[i].subject_public_key();
- if(key->algo_name() == "RSA")
- have_rsa = true;
-
- if(key->algo_name() == "DSA")
- have_dsa = true;
- }
-
- suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa);
-
- if(suite == 0)
- throw TLS_Exception(PROTOCOL_VERSION,
- "Can't agree on a ciphersuite with client");
-
- comp_algo = policy.choose_compression(c_hello.compression_algos());
-
- s_version = ver;
- s_random = rng.random_vec(32);
-
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello message
-*/
-SecureVector<byte> Server_Hello::serialize() const
- {
- SecureVector<byte> buf;
-
- buf.push_back(static_cast<byte>(s_version >> 8));
- buf.push_back(static_cast<byte>(s_version ));
- buf += s_random;
-
- append_tls_length_value(buf, sess_id, 1);
-
- buf.push_back(get_byte(0, suite));
- buf.push_back(get_byte(1, suite));
-
- buf.push_back(comp_algo);
-
- return buf;
- }
-
-/*
-* Deserialize a Server Hello message
-*/
-void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size() < 38)
- throw Decoding_Error("Server_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- s_version = static_cast<Version_Code>(reader.get_u16bit());
-
- if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11)
- {
- throw TLS_Exception(PROTOCOL_VERSION,
- "Server_Hello: Unsupported server version");
- }
-
- s_random = reader.get_fixed<byte>(32);
-
- sess_id = reader.get_range<byte>(1, 0, 32);
-
- suite = reader.get_u16bit();
-
- comp_algo = reader.get_byte();
- }
-
-/*
-* Create a new Server Hello Done message
-*/
-Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
- HandshakeHash& hash)
- {
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello Done message
-*/
-SecureVector<byte> Server_Hello_Done::serialize() const
- {
- return SecureVector<byte>();
- }
-
-/*
-* Deserialize a Server Hello Done message
-*/
-void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
- }
-
-}
diff --git a/src/ssl/info.txt b/src/ssl/info.txt
deleted file mode 100644
index fd2c255fc..000000000
--- a/src/ssl/info.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-define SSL_TLS
-
-load_on request
-
-<comment>
-A new TLS API is being developed. This version has numerous
-performance and usability issues and will not be supported in the
-future. Only use it if you need it for compatability with code written
-against previous versions.
-</comment>
-
-uses_tr1 yes
-
-<header:public>
-tls_client.h
-tls_connection.h
-tls_exceptn.h
-tls_magic.h
-tls_policy.h
-tls_record.h
-tls_server.h
-tls_session_key.h
-tls_suites.h
-</header:public>
-
-<header:internal>
-tls_alerts.h
-tls_handshake_hash.h
-tls_messages.h
-tls_reader.h
-tls_state.h
-</header:internal>
-
-<source>
-c_kex.cpp
-cert_req.cpp
-cert_ver.cpp
-finished.cpp
-tls_handshake_hash.cpp
-hello.cpp
-rec_read.cpp
-rec_wri.cpp
-s_kex.cpp
-tls_client.cpp
-tls_policy.cpp
-tls_server.cpp
-tls_session_key.cpp
-tls_state.cpp
-tls_suites.cpp
-</source>
-
-<requires>
-aes
-arc4
-asn1
-des
-dh
-dsa
-eme_pkcs
-emsa3
-filters
-hmac
-md5
-prf_ssl3
-prf_tls
-rng
-rsa
-sha1
-ssl3mac
-x509
-</requires>
diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp
deleted file mode 100644
index 7e295f8a4..000000000
--- a/src/ssl/rec_read.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-* TLS Record Reading
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_record.h>
-#include <botan/lookup.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-/*
-* Reset the state
-*/
-void Record_Reader::reset()
- {
- cipher.reset();
-
- delete mac;
- mac = 0;
-
- mac_size = 0;
- block_size = 0;
- iv_size = 0;
- major = minor = 0;
- seq_no = 0;
- }
-
-/*
-* Set the version to use
-*/
-void Record_Reader::set_version(Version_Code version)
- {
- if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11)
- throw Invalid_Argument("Record_Reader: Invalid protocol version");
-
- major = (version >> 8) & 0xFF;
- minor = (version & 0xFF);
- }
-
-/*
-* Set the keys for reading
-*/
-void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys,
- Connection_Side side)
- {
- cipher.reset();
- delete mac;
- mac = 0;
-
- SymmetricKey mac_key, cipher_key;
- InitializationVector iv;
-
- if(side == CLIENT)
- {
- cipher_key = keys.server_cipher_key();
- iv = keys.server_iv();
- mac_key = keys.server_mac_key();
- }
- else
- {
- cipher_key = keys.client_cipher_key();
- iv = keys.client_iv();
- mac_key = keys.client_mac_key();
- }
-
- const std::string cipher_algo = suite.cipher_algo();
- const std::string mac_algo = suite.mac_algo();
-
- if(have_block_cipher(cipher_algo))
- {
- cipher.append(get_cipher(
- cipher_algo + "/CBC/NoPadding",
- cipher_key, iv, DECRYPTION)
- );
- block_size = block_size_of(cipher_algo);
-
- if(major > 3 || (major == 3 && minor >= 2))
- iv_size = block_size;
- else
- iv_size = 0;
- }
- else if(have_stream_cipher(cipher_algo))
- {
- cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION));
- block_size = 0;
- iv_size = 0;
- }
- else
- throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo);
-
- if(have_hash(mac_algo))
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- if(major == 3 && minor == 0)
- mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
- else
- mac = af.make_mac("HMAC(" + mac_algo + ")");
-
- mac->set_key(mac_key);
- mac_size = mac->output_length();
- }
- else
- throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo);
- }
-
-void Record_Reader::add_input(const byte input[], size_t input_size)
- {
- input_queue.write(input, input_size);
- }
-
-/*
-* Retrieve the next record
-*/
-size_t Record_Reader::get_record(byte& msg_type,
- MemoryRegion<byte>& output)
- {
- byte header[5] = { 0 };
-
- const size_t have_in_queue = input_queue.size();
-
- if(have_in_queue < sizeof(header))
- return (sizeof(header) - have_in_queue);
-
- /*
- * We peek first to make sure we have the full record
- */
- input_queue.peek(header, sizeof(header));
-
- // SSLv2-format client hello?
- if(header[0] & 0x80 && header[2] == 1 && header[3] == 3)
- {
- size_t record_len = make_u16bit(header[0], header[1]) & 0x7FFF;
-
- if(have_in_queue < record_len + 2)
- return (record_len + 2 - have_in_queue);
-
- msg_type = HANDSHAKE;
- output.resize(record_len + 4);
-
- input_queue.read(&output[2], record_len + 2);
- output[0] = CLIENT_HELLO_SSLV2;
- output[1] = 0;
- output[2] = header[0] & 0x7F;
- output[3] = header[1];
-
- return 0;
- }
-
- if(header[0] != CHANGE_CIPHER_SPEC &&
- header[0] != ALERT &&
- header[0] != HANDSHAKE &&
- header[0] != APPLICATION_DATA)
- {
- throw TLS_Exception(UNEXPECTED_MESSAGE,
- "Record_Reader: Unknown record type");
- }
-
- const u16bit version = make_u16bit(header[1], header[2]);
- const u16bit record_len = make_u16bit(header[3], header[4]);
-
- if(major && (header[1] != major || header[2] != minor))
- throw TLS_Exception(PROTOCOL_VERSION,
- "Record_Reader: Got unexpected version");
-
- // If insufficient data, return without doing anything
- if(have_in_queue < (sizeof(header) + record_len))
- return (sizeof(header) + record_len - have_in_queue);
-
- SecureVector<byte> buffer(record_len);
-
- input_queue.read(header, sizeof(header)); // pull off the header
- input_queue.read(&buffer[0], buffer.size());
-
- /*
- * We are handshaking, no crypto to do so return as-is
- * TODO: Check msg_type to confirm a handshake?
- */
- if(mac_size == 0)
- {
- msg_type = header[0];
- output = buffer;
- return 0; // got a full record
- }
-
- // Otherwise, decrypt, check MAC, return plaintext
-
- cipher.process_msg(buffer);
- SecureVector<byte> plaintext = cipher.read_all(Pipe::LAST_MESSAGE);
-
- size_t pad_size = 0;
-
- if(block_size)
- {
- byte pad_value = plaintext[plaintext.size()-1];
- pad_size = pad_value + 1;
-
- /*
- * Check the padding; if it is wrong, then say we have 0 bytes of
- * padding, which should ensure that the MAC check below does not
- * suceed. This hides a timing channel.
- *
- * This particular countermeasure is recommended in the TLS 1.2
- * spec (RFC 5246) in section 6.2.3.2
- */
- if(version == SSL_V3)
- {
- if(pad_value > block_size)
- pad_size = 0;
- }
- else
- {
- bool padding_good = true;
-
- for(size_t i = 0; i != pad_size; ++i)
- if(plaintext[plaintext.size()-i-1] != pad_value)
- padding_good = false;
-
- if(!padding_good)
- pad_size = 0;
- }
- }
-
- if(plaintext.size() < mac_size + pad_size + iv_size)
- throw Decoding_Error("Record_Reader: Record truncated");
-
- const size_t mac_offset = plaintext.size() - (mac_size + pad_size);
- SecureVector<byte> received_mac(&plaintext[mac_offset],
- mac_size);
-
- const u16bit plain_length = plaintext.size() - (mac_size + pad_size + iv_size);
-
- mac->update_be(seq_no);
- mac->update(header[0]); // msg_type
-
- if(version != SSL_V3)
- for(size_t i = 0; i != 2; ++i)
- mac->update(get_byte(i, version));
-
- mac->update_be(plain_length);
- mac->update(&plaintext[iv_size], plain_length);
-
- ++seq_no;
-
- SecureVector<byte> computed_mac = mac->final();
-
- if(received_mac != computed_mac)
- throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure");
-
- msg_type = header[0];
-
- output.resize(plain_length);
- copy_mem(&output[0], &plaintext[iv_size], plain_length);
- return 0;
- }
-
-}
diff --git a/src/ssl/rec_wri.cpp b/src/ssl/rec_wri.cpp
deleted file mode 100644
index 59dead3cd..000000000
--- a/src/ssl/rec_wri.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
-* TLS Record Writing
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_record.h>
-#include <botan/internal/tls_handshake_hash.h>
-#include <botan/lookup.h>
-#include <botan/loadstor.h>
-#include <botan/libstate.h>
-
-namespace Botan {
-
-/**
-* Record_Writer Constructor
-*/
-Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out) :
- output_fn(out),
- buffer(DEFAULT_BUFFERSIZE)
- {
- mac = 0;
- reset();
- }
-
-/**
-* Reset the state
-*/
-void Record_Writer::reset()
- {
- cipher.reset();
-
- delete mac;
- mac = 0;
-
- zeroise(buffer);
- buf_pos = 0;
-
- major = minor = buf_type = 0;
- block_size = 0;
- mac_size = 0;
- iv_size = 0;
-
- seq_no = 0;
- }
-
-/**
-* Set the version to use
-*/
-void Record_Writer::set_version(Version_Code version)
- {
- if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11)
- throw Invalid_Argument("Record_Writer: Invalid protocol version");
-
- major = (version >> 8) & 0xFF;
- minor = (version & 0xFF);
- }
-
-/**
-* Set the keys for writing
-*/
-void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys,
- Connection_Side side)
- {
- cipher.reset();
- delete mac;
- mac = 0;
-
- SymmetricKey mac_key, cipher_key;
- InitializationVector iv;
-
- if(side == CLIENT)
- {
- cipher_key = keys.client_cipher_key();
- iv = keys.client_iv();
- mac_key = keys.client_mac_key();
- }
- else
- {
- cipher_key = keys.server_cipher_key();
- iv = keys.server_iv();
- mac_key = keys.server_mac_key();
- }
-
- const std::string cipher_algo = suite.cipher_algo();
- const std::string mac_algo = suite.mac_algo();
-
- if(have_block_cipher(cipher_algo))
- {
- cipher.append(get_cipher(
- cipher_algo + "/CBC/NoPadding",
- cipher_key, iv, ENCRYPTION)
- );
- block_size = block_size_of(cipher_algo);
-
- if(major > 3 || (major == 3 && minor >= 2))
- iv_size = block_size;
- else
- iv_size = 0;
- }
- else if(have_stream_cipher(cipher_algo))
- {
- cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION));
- block_size = 0;
- iv_size = 0;
- }
- else
- throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo);
-
- if(have_hash(mac_algo))
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- if(major == 3 && minor == 0)
- mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
- else
- mac = af.make_mac("HMAC(" + mac_algo + ")");
-
- mac->set_key(mac_key);
- mac_size = mac->output_length();
- }
- else
- throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo);
- }
-
-/**
-* Send one or more records to the other side
-*/
-void Record_Writer::send(byte type, const byte input[], size_t length)
- {
- if(type != buf_type)
- flush();
-
- const size_t BUFFER_SIZE = buffer.size();
- buf_type = type;
-
- // FIXME: compression right here
-
- buffer.copy(buf_pos, input, length);
- if(buf_pos + length >= BUFFER_SIZE)
- {
- send_record(buf_type, &buffer[0], length);
- input += (BUFFER_SIZE - buf_pos);
- length -= (BUFFER_SIZE - buf_pos);
- while(length >= BUFFER_SIZE)
- {
- send_record(buf_type, input, BUFFER_SIZE);
- input += BUFFER_SIZE;
- length -= BUFFER_SIZE;
- }
- buffer.copy(input, length);
- buf_pos = 0;
- }
- buf_pos += length;
- }
-
-/**
-* Split buffer into records, and send them all
-*/
-void Record_Writer::flush()
- {
- const byte* buf_ptr = &buffer[0];
- size_t offset = 0;
-
- while(offset != buf_pos)
- {
- size_t record_size = buf_pos - offset;
- if(record_size > MAX_PLAINTEXT_SIZE)
- record_size = MAX_PLAINTEXT_SIZE;
-
- send_record(buf_type, buf_ptr + offset, record_size);
- offset += record_size;
- }
- buf_type = 0;
- buf_pos = 0;
- }
-
-/**
-* Encrypt and send the record
-*/
-void Record_Writer::send_record(byte type, const byte buf[], size_t length)
- {
- if(length >= MAX_COMPRESSED_SIZE)
- throw TLS_Exception(INTERNAL_ERROR,
- "Record_Writer: Compressed packet is too big");
-
- if(mac_size == 0)
- send_record(type, major, minor, buf, length);
- else
- {
- mac->update_be(seq_no);
- mac->update(type);
-
- if(major > 3 || (major == 3 && minor != 0))
- {
- mac->update(major);
- mac->update(minor);
- }
-
- mac->update(get_byte<u16bit>(0, length));
- mac->update(get_byte<u16bit>(1, length));
- mac->update(buf, length);
-
- SecureVector<byte> buf_mac = mac->final();
-
- // TODO: This could all use a single buffer
- cipher.start_msg();
-
- if(iv_size)
- {
- RandomNumberGenerator& rng = global_state().global_rng();
-
- SecureVector<byte> random_iv(iv_size);
-
- rng.randomize(&random_iv[0], random_iv.size());
-
- cipher.write(random_iv);
- }
-
- cipher.write(buf, length);
- cipher.write(buf_mac);
-
- if(block_size)
- {
- size_t pad_val =
- (block_size - (1 + length + buf_mac.size())) % block_size;
-
- for(size_t i = 0; i != pad_val + 1; ++i)
- cipher.write(pad_val);
- }
- cipher.end_msg();
-
- SecureVector<byte> output = cipher.read_all(Pipe::LAST_MESSAGE);
-
- send_record(type, major, minor, &output[0], output.size());
-
- seq_no++;
- }
- }
-
-/**
-* Send a final record packet
-*/
-void Record_Writer::send_record(byte type, byte major, byte minor,
- const byte out[], size_t length)
- {
- if(length >= MAX_CIPHERTEXT_SIZE)
- throw TLS_Exception(INTERNAL_ERROR,
- "Record_Writer: Record is too big");
-
- byte header[5] = { type, major, minor, 0 };
- for(size_t i = 0; i != 2; ++i)
- header[i+3] = get_byte<u16bit>(i, length);
-
- output_fn(header, 5);
- output_fn(out, length);
- }
-
-/**
-* Send an alert
-*/
-void Record_Writer::alert(Alert_Level level, Alert_Type type)
- {
- byte alert[2] = { level, type };
- send(ALERT, alert, sizeof(alert));
- flush();
- }
-
-}
diff --git a/src/ssl/s_kex.cpp b/src/ssl/s_kex.cpp
deleted file mode 100644
index 1e7de31d0..000000000
--- a/src/ssl/s_kex.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-* Server Key Exchange Message
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/pubkey.h>
-#include <botan/dh.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <botan/loadstor.h>
-#include <memory>
-
-namespace Botan {
-
-/**
-* Create a new Server Key Exchange message
-*/
-Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng,
- Record_Writer& writer,
- const Public_Key* kex_key,
- const Private_Key* priv_key,
- const MemoryRegion<byte>& c_random,
- const MemoryRegion<byte>& s_random,
- HandshakeHash& hash)
- {
- const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(kex_key);
- const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(kex_key);
-
- if(dh_pub)
- {
- params.push_back(dh_pub->get_domain().get_p());
- params.push_back(dh_pub->get_domain().get_g());
- params.push_back(BigInt::decode(dh_pub->public_value()));
- }
- else if(rsa_pub)
- {
- params.push_back(rsa_pub->get_n());
- params.push_back(rsa_pub->get_e());
- }
- else
- throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA");
-
-
- std::string padding = "";
- Signature_Format format = IEEE_1363;
-
- if(priv_key->algo_name() == "RSA")
- padding = "EMSA3(TLS.Digest.0)";
- else if(priv_key->algo_name() == "DSA")
- {
- padding = "EMSA1(SHA-1)";
- format = DER_SEQUENCE;
- }
- else
- throw Invalid_Argument(priv_key->algo_name() +
- " is invalid/unknown for TLS signatures");
-
- PK_Signer signer(*priv_key, padding, format);
-
- signer.update(c_random);
- signer.update(s_random);
- signer.update(serialize_params());
- signature = signer.signature(rng);
-
- send(writer, hash);
- }
-
-/**
-* Serialize a Server Key Exchange message
-*/
-SecureVector<byte> Server_Key_Exchange::serialize() const
- {
- SecureVector<byte> buf = serialize_params();
- append_tls_length_value(buf, signature, 2);
- return buf;
- }
-
-/**
-* Serialize the ServerParams structure
-*/
-SecureVector<byte> Server_Key_Exchange::serialize_params() const
- {
- SecureVector<byte> buf;
-
- for(size_t i = 0; i != params.size(); ++i)
- append_tls_length_value(buf, BigInt::encode(params[i]), 2);
-
- return buf;
- }
-
-/**
-* Deserialize a Server Key Exchange message
-*/
-void Server_Key_Exchange::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size() < 6)
- throw Decoding_Error("Server_Key_Exchange: Packet corrupted");
-
- SecureVector<byte> values[4];
- size_t so_far = 0;
-
- for(size_t i = 0; i != 4; ++i)
- {
- const u16bit len = make_u16bit(buf[so_far], buf[so_far+1]);
- so_far += 2;
-
- if(len + so_far > buf.size())
- throw Decoding_Error("Server_Key_Exchange: Packet corrupted");
-
- values[i].resize(len);
- copy_mem(&values[i][0], &buf[so_far], len);
- so_far += len;
-
- if(i == 2 && so_far == buf.size())
- break;
- }
-
- params.push_back(BigInt::decode(values[0]));
- params.push_back(BigInt::decode(values[1]));
- if(values[3].size())
- {
- params.push_back(BigInt::decode(values[2]));
- signature = values[3];
- }
- else
- signature = values[2];
- }
-
-/**
-* Return the public key
-*/
-Public_Key* Server_Key_Exchange::key() const
- {
- if(params.size() == 2)
- return new RSA_PublicKey(params[0], params[1]);
- else if(params.size() == 3)
- return new DH_PublicKey(DL_Group(params[0], params[1]), params[2]);
- else
- throw Internal_Error("Server_Key_Exchange::key: No key set");
- }
-
-/**
-* Verify a Server Key Exchange message
-*/
-bool Server_Key_Exchange::verify(const X509_Certificate& cert,
- const MemoryRegion<byte>& c_random,
- const MemoryRegion<byte>& s_random) const
- {
-
- std::auto_ptr<Public_Key> key(cert.subject_public_key());
-
- std::string padding = "";
- Signature_Format format = IEEE_1363;
-
- if(key->algo_name() == "RSA")
- padding = "EMSA3(TLS.Digest.0)";
- else if(key->algo_name() == "DSA")
- {
- padding == "EMSA1(SHA-1)";
- format = DER_SEQUENCE;
- }
- else
- throw Invalid_Argument(key->algo_name() +
- " is invalid/unknown for TLS signatures");
-
- PK_Verifier verifier(*key, padding, format);
-
- SecureVector<byte> params_got = serialize_params();
- verifier.update(c_random);
- verifier.update(s_random);
- verifier.update(params_got);
-
- return verifier.check_signature(signature);
- }
-
-}
diff --git a/src/ssl/tls_alerts.h b/src/ssl/tls_alerts.h
deleted file mode 100644
index 241599aa8..000000000
--- a/src/ssl/tls_alerts.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-* Alert Message
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_ALERT_H__
-#define BOTAN_TLS_ALERT_H__
-
-#include <botan/tls_exceptn.h>
-
-namespace Botan {
-
-/**
-* SSL/TLS Alert Message
-*/
-class Alert
- {
- public:
- /**
- * @return if this alert is a fatal one or not
- */
- bool is_fatal() const { return fatal; }
-
- /**
- * @return type of alert
- */
- Alert_Type type() const { return type_code; }
-
- /**
- * Deserialize an Alert message
- * @param buf the serialized alert
- */
- Alert(const MemoryRegion<byte>& buf)
- {
- if(buf.size() != 2)
- throw Decoding_Error("Alert: Bad size for alert message");
-
- if(buf[0] == 1) fatal = false;
- else if(buf[0] == 2) fatal = true;
- else
- throw Decoding_Error("Alert: Bad type code for alert level");
-
- type_code = static_cast<Alert_Type>(buf[1]);
- }
- private:
- bool fatal;
- Alert_Type type_code;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_client.cpp b/src/ssl/tls_client.cpp
deleted file mode 100644
index a136752fd..000000000
--- a/src/ssl/tls_client.cpp
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
-* TLS Client
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_client.h>
-#include <botan/internal/tls_alerts.h>
-#include <botan/internal/tls_state.h>
-#include <botan/loadstor.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <botan/dh.h>
-
-namespace Botan {
-
-namespace {
-
-/**
-* Verify the state transition is allowed
-* FIXME: checks are wrong for session reuse (add a flag for that)
-*/
-void client_check_state(Handshake_Type new_msg, Handshake_State* state)
- {
- class State_Transition_Error : public Unexpected_Message
- {
- public:
- State_Transition_Error(const std::string& err) :
- Unexpected_Message("State transition error from " + err) {}
- };
-
- if(new_msg == HELLO_REQUEST)
- {
- if(state->client_hello)
- throw State_Transition_Error("HelloRequest");
- }
- else if(new_msg == SERVER_HELLO)
- {
- if(!state->client_hello || state->server_hello)
- throw State_Transition_Error("ServerHello");
- }
- else if(new_msg == CERTIFICATE)
- {
- if(!state->server_hello || state->server_kex ||
- state->cert_req || state->server_hello_done)
- throw State_Transition_Error("ServerCertificate");
- }
- else if(new_msg == SERVER_KEX)
- {
- if(!state->server_hello || state->server_kex ||
- state->cert_req || state->server_hello_done)
- throw State_Transition_Error("ServerKeyExchange");
- }
- else if(new_msg == CERTIFICATE_REQUEST)
- {
- if(!state->server_certs || state->cert_req || state->server_hello_done)
- throw State_Transition_Error("CertificateRequest");
- }
- else if(new_msg == SERVER_HELLO_DONE)
- {
- if(!state->server_hello || state->server_hello_done)
- throw State_Transition_Error("ServerHelloDone");
- }
- else if(new_msg == HANDSHAKE_CCS)
- {
- if(!state->client_finished || state->server_finished)
- throw State_Transition_Error("ServerChangeCipherSpec");
- }
- else if(new_msg == FINISHED)
- {
- if(!state->got_server_ccs)
- throw State_Transition_Error("ServerFinished");
- }
- else
- throw Unexpected_Message("Unexpected message in handshake");
- }
-
-}
-
-/**
-* TLS Client Constructor
-*/
-TLS_Client::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) :
- input_fn(input_fn),
- policy(policy),
- rng(rng),
- writer(output_fn)
- {
- initialize();
- }
-
-void TLS_Client::add_client_cert(const X509_Certificate& cert,
- Private_Key* cert_key)
- {
- certs.push_back(std::make_pair(cert, cert_key));
- }
-
-/**
-* TLS Client Destructor
-*/
-TLS_Client::~TLS_Client()
- {
- close();
- for(size_t i = 0; i != certs.size(); i++)
- delete certs[i].second;
- delete state;
- }
-
-/**
-* Initialize a TLS client connection
-*/
-void TLS_Client::initialize()
- {
- std::string error_str;
- Alert_Type error_type = NO_ALERT_TYPE;
-
- try {
- state = 0;
- active = false;
- writer.set_version(policy.pref_version());
- do_handshake();
- }
- catch(TLS_Exception& e)
- {
- error_str = e.what();
- error_type = e.type();
- }
- catch(std::exception& e)
- {
- error_str = e.what();
- error_type = HANDSHAKE_FAILURE;
- }
-
- if(error_type != NO_ALERT_TYPE)
- {
- if(active)
- {
- active = false;
- reader.reset();
-
- writer.alert(FATAL, error_type);
- writer.reset();
- }
-
- if(state)
- {
- delete state;
- state = 0;
- }
-
- throw Stream_IO_Error("TLS_Client: Handshake failed: " + error_str);
- }
- }
-
-/**
-* Return the peer's certificate chain
-*/
-std::vector<X509_Certificate> TLS_Client::peer_cert_chain() const
- {
- return peer_certs;
- }
-
-/**
-* Write to a TLS connection
-*/
-void TLS_Client::write(const byte buf[], size_t length)
- {
- if(!active)
- throw TLS_Exception(INTERNAL_ERROR,
- "TLS_Client::write called while closed");
-
- writer.send(APPLICATION_DATA, buf, length);
- }
-
-/**
-* Read from a TLS connection
-*/
-size_t TLS_Client::read(byte out[], size_t length)
- {
- if(!active)
- return 0;
-
- writer.flush();
-
- while(read_buf.size() == 0)
- {
- state_machine();
- if(active == false)
- break;
- }
-
- size_t got = std::min<size_t>(read_buf.size(), length);
- read_buf.read(out, got);
- return got;
- }
-
-/**
-* Close a TLS connection
-*/
-void TLS_Client::close()
- {
- close(WARNING, CLOSE_NOTIFY);
- }
-
-/**
-* Check connection status
-*/
-bool TLS_Client::is_closed() const
- {
- if(!active)
- return true;
- return false;
- }
-
-/**
-* Close a TLS connection
-*/
-void TLS_Client::close(Alert_Level level, Alert_Type alert_code)
- {
- if(active)
- {
- try {
- writer.alert(level, alert_code);
- writer.flush();
- }
- catch(...) {}
-
- active = false;
- }
- }
-
-/**
-* Iterate the TLS state machine
-*/
-void TLS_Client::state_machine()
- {
- byte rec_type = CONNECTION_CLOSED;
- SecureVector<byte> record(1024);
-
- size_t bytes_needed = reader.get_record(rec_type, record);
-
- while(bytes_needed)
- {
- size_t to_get = std::min<size_t>(record.size(), bytes_needed);
- size_t got = input_fn(&record[0], to_get);
-
- if(got == 0)
- {
- rec_type = CONNECTION_CLOSED;
- break;
- }
-
- reader.add_input(&record[0], got);
-
- bytes_needed = reader.get_record(rec_type, record);
- }
-
- if(rec_type == CONNECTION_CLOSED)
- {
- active = false;
- reader.reset();
- writer.reset();
- }
- else if(rec_type == APPLICATION_DATA)
- {
- if(active)
- read_buf.write(&record[0], record.size());
- else
- throw Unexpected_Message("Application data before handshake done");
- }
- else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC)
- read_handshake(rec_type, record);
- else if(rec_type == ALERT)
- {
- Alert alert(record);
-
- if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY)
- {
- if(alert.type() == CLOSE_NOTIFY)
- writer.alert(WARNING, CLOSE_NOTIFY);
-
- reader.reset();
- writer.reset();
- active = false;
- if(state)
- {
- delete state;
- state = 0;
- }
- }
- }
- else
- throw Unexpected_Message("Unknown message type received");
- }
-
-/**
-* Split up and process handshake messages
-*/
-void TLS_Client::read_handshake(byte rec_type,
- const MemoryRegion<byte>& rec_buf)
- {
- if(rec_type == HANDSHAKE)
- state->queue.write(&rec_buf[0], rec_buf.size());
-
- while(true)
- {
- Handshake_Type type = HANDSHAKE_NONE;
- SecureVector<byte> contents;
-
- if(rec_type == HANDSHAKE)
- {
- if(state->queue.size() >= 4)
- {
- byte head[4] = { 0 };
- state->queue.peek(head, 4);
-
- const size_t length = make_u32bit(0, head[1], head[2], head[3]);
-
- if(state->queue.size() >= length + 4)
- {
- type = static_cast<Handshake_Type>(head[0]);
- contents.resize(length);
- state->queue.read(head, 4);
- state->queue.read(&contents[0], contents.size());
- }
- }
- }
- else if(rec_type == CHANGE_CIPHER_SPEC)
- {
- if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1)
- type = HANDSHAKE_CCS;
- else
- throw Decoding_Error("Malformed ChangeCipherSpec message");
- }
- else
- throw Decoding_Error("Unknown message type in handshake processing");
-
- if(type == HANDSHAKE_NONE)
- break;
-
- process_handshake_msg(type, contents);
-
- if(type == HANDSHAKE_CCS || !state)
- break;
- }
- }
-
-/**
-* Process a handshake message
-*/
-void TLS_Client::process_handshake_msg(Handshake_Type type,
- const MemoryRegion<byte>& contents)
- {
- rng.add_entropy(&contents[0], contents.size());
-
- if(type == HELLO_REQUEST)
- {
- if(state == 0)
- state = new Handshake_State();
- else
- return;
- }
-
- if(state == 0)
- throw Unexpected_Message("Unexpected handshake message");
-
- if(type != HANDSHAKE_CCS && type != HELLO_REQUEST && type != FINISHED)
- {
- state->hash.update(static_cast<byte>(type));
- const size_t record_length = contents.size();
- for(size_t i = 0; i != 3; i++)
- state->hash.update(get_byte<u32bit>(i+1, record_length));
- state->hash.update(contents);
- }
-
- if(type == HELLO_REQUEST)
- {
- client_check_state(type, state);
-
- Hello_Request hello_request(contents);
- state->client_hello = new Client_Hello(rng, writer, policy, state->hash);
- }
- else if(type == SERVER_HELLO)
- {
- client_check_state(type, state);
-
- state->server_hello = new Server_Hello(contents);
-
- if(!state->client_hello->offered_suite(
- state->server_hello->ciphersuite()
- )
- )
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "TLS_Client: Server replied with bad ciphersuite");
-
- state->version = state->server_hello->version();
-
- if(state->version > state->client_hello->version())
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "TLS_Client: Server replied with bad version");
-
- if(state->version < policy.min_version())
- throw TLS_Exception(PROTOCOL_VERSION,
- "TLS_Client: Server is too old for specified policy");
-
- writer.set_version(state->version);
- reader.set_version(state->version);
-
- state->suite = CipherSuite(state->server_hello->ciphersuite());
- }
- else if(type == CERTIFICATE)
- {
- client_check_state(type, state);
-
- if(state->suite.sig_type() == TLS_ALGO_SIGNER_ANON)
- throw Unexpected_Message("Recived certificate from anonymous server");
-
- state->server_certs = new Certificate(contents);
-
- peer_certs = state->server_certs->cert_chain();
- if(peer_certs.size() == 0)
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "TLS_Client: No certificates sent by server");
-
- if(!policy.check_cert(peer_certs))
- throw TLS_Exception(BAD_CERTIFICATE,
- "TLS_Client: Server certificate is not valid");
-
- state->kex_pub = peer_certs[0].subject_public_key();
-
- bool is_dsa = false, is_rsa = false;
-
- if(dynamic_cast<DSA_PublicKey*>(state->kex_pub))
- is_dsa = true;
- else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub))
- is_rsa = true;
- else
- throw TLS_Exception(UNSUPPORTED_CERTIFICATE,
- "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))
- throw TLS_Exception(ILLEGAL_PARAMETER,
- "Certificate key type did not match ciphersuite");
- }
- else if(type == SERVER_KEX)
- {
- client_check_state(type, state);
-
- if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_NOKEX)
- throw Unexpected_Message("Unexpected key exchange from server");
-
- state->server_kex = new Server_Key_Exchange(contents);
-
- if(state->kex_pub)
- delete state->kex_pub;
-
- state->kex_pub = state->server_kex->key();
-
- bool is_dh = false, is_rsa = false;
-
- if(dynamic_cast<DH_PublicKey*>(state->kex_pub))
- is_dh = true;
- else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub))
- is_rsa = true;
- else
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "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))
- throw TLS_Exception(ILLEGAL_PARAMETER,
- "Certificate key type did not match ciphersuite");
-
- if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON)
- {
- if(!state->server_kex->verify(peer_certs[0],
- state->client_hello->random(),
- state->server_hello->random()))
- throw TLS_Exception(DECRYPT_ERROR,
- "Bad signature on server key exchange");
- }
- }
- else if(type == CERTIFICATE_REQUEST)
- {
- client_check_state(type, state);
-
- state->cert_req = new Certificate_Req(contents);
- state->do_client_auth = true;
- }
- else if(type == SERVER_HELLO_DONE)
- {
- client_check_state(type, state);
-
- state->server_hello_done = new Server_Hello_Done(contents);
-
- if(state->do_client_auth)
- {
- std::vector<X509_Certificate> send_certs;
-
- std::vector<Certificate_Type> types =
- state->cert_req->acceptable_types();
-
- // FIXME: Fill in useful certs here, if any
- state->client_certs = new Certificate(writer, send_certs,
- state->hash);
- }
-
- state->client_kex =
- new Client_Key_Exchange(rng, writer, state->hash,
- state->kex_pub, state->version,
- state->client_hello->version());
-
- if(state->do_client_auth)
- {
- Private_Key* key_matching_cert = 0; // FIXME
- state->client_verify = new Certificate_Verify(rng,
- writer, state->hash,
- key_matching_cert);
- }
-
- state->keys = SessionKeys(state->suite, state->version,
- state->client_kex->pre_master_secret(),
- state->client_hello->random(),
- state->server_hello->random());
-
- writer.send(CHANGE_CIPHER_SPEC, 1);
- writer.flush();
-
- writer.set_keys(state->suite, state->keys, CLIENT);
-
- state->client_finished = new Finished(writer, state->version, CLIENT,
- state->keys.master_secret(),
- state->hash);
- }
- else if(type == HANDSHAKE_CCS)
- {
- client_check_state(type, state);
-
- reader.set_keys(state->suite, state->keys, CLIENT);
- state->got_server_ccs = true;
- }
- else if(type == FINISHED)
- {
- client_check_state(type, state);
-
- state->server_finished = new Finished(contents);
-
- if(!state->server_finished->verify(state->keys.master_secret(),
- state->version, state->hash, SERVER))
- throw TLS_Exception(DECRYPT_ERROR,
- "Finished message didn't verify");
-
- delete state;
- state = 0;
- active = true;
- }
- else
- throw Unexpected_Message("Unknown handshake message received");
- }
-
-/**
-* Perform a client-side TLS handshake
-*/
-void TLS_Client::do_handshake()
- {
- state = new Handshake_State;
-
- state->client_hello = new Client_Hello(rng, writer, policy, state->hash);
-
- while(true)
- {
- if(active && !state)
- break;
- if(!active && !state)
- throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed (do_handshake)");
-
- state_machine();
- }
- }
-
-}
diff --git a/src/ssl/tls_client.h b/src/ssl/tls_client.h
deleted file mode 100644
index 7d2ce9cda..000000000
--- a/src/ssl/tls_client.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-* TLS Client
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CLIENT_H__
-#define BOTAN_TLS_CLIENT_H__
-
-#include <botan/tls_connection.h>
-#include <botan/tls_policy.h>
-#include <botan/tls_record.h>
-#include <vector>
-#include <string>
-
-namespace Botan {
-
-/**
-* SSL/TLS Client
-*/
-class BOTAN_DLL TLS_Client : public TLS_Connection
- {
- public:
- size_t read(byte buf[], size_t buf_len);
- void write(const byte buf[], size_t buf_len);
-
- void close();
- bool is_closed() const;
-
- std::vector<X509_Certificate> peer_cert_chain() const;
-
- void add_client_cert(const X509_Certificate& cert,
- Private_Key* cert_key);
-
- 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);
-
- ~TLS_Client();
- private:
- void close(Alert_Level, Alert_Type);
-
- size_t get_pending_socket_input(byte output[], size_t length);
-
- void initialize();
- void do_handshake();
-
- void state_machine();
- void read_handshake(byte, const MemoryRegion<byte>&);
- void process_handshake_msg(Handshake_Type, const MemoryRegion<byte>&);
-
- std::tr1::function<size_t (byte[], size_t)> input_fn;
-
- const TLS_Policy& policy;
- RandomNumberGenerator& rng;
-
- Record_Writer writer;
- Record_Reader reader;
-
- std::vector<X509_Certificate> peer_certs;
- std::vector<std::pair<X509_Certificate, Private_Key*> > certs;
-
- class Handshake_State* state;
- SecureVector<byte> session_id;
- SecureQueue read_buf;
- bool active;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_connection.h b/src/ssl/tls_connection.h
deleted file mode 100644
index bbefa2114..000000000
--- a/src/ssl/tls_connection.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-* TLS Connection
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CONNECTION_H__
-#define BOTAN_TLS_CONNECTION_H__
-
-#include <botan/x509cert.h>
-#include <vector>
-
-namespace Botan {
-
-/**
-* TLS Connection
-*/
-class BOTAN_DLL TLS_Connection
- {
- public:
- virtual size_t read(byte[], size_t) = 0;
- virtual void write(const byte[], size_t) = 0;
- size_t read(byte& in) { return read(&in, 1); }
- void write(byte out) { write(&out, 1); }
-
- virtual std::vector<X509_Certificate> peer_cert_chain() const = 0;
-
- virtual void close() = 0;
-
- virtual ~TLS_Connection() {}
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_handshake_hash.cpp b/src/ssl/tls_handshake_hash.cpp
deleted file mode 100644
index 7c1e2e385..000000000
--- a/src/ssl/tls_handshake_hash.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-* TLS Handshake Hash
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_handshake_hash.h>
-#include <botan/md5.h>
-#include <botan/sha160.h>
-#include <memory>
-
-namespace Botan {
-
-/**
-* Return a TLS Handshake Hash
-*/
-SecureVector<byte> HandshakeHash::final()
- {
- MD5 md5;
- SHA_160 sha1;
-
- md5.update(data);
- sha1.update(data);
-
- SecureVector<byte> output;
- output += md5.final();
- output += sha1.final();
- return output;
- }
-
-/**
-* Return a SSLv3 Handshake Hash
-*/
-SecureVector<byte> HandshakeHash::final_ssl3(const MemoryRegion<byte>& secret)
- {
- const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C;
-
- MD5 md5;
- SHA_160 sha1;
-
- md5.update(data);
- sha1.update(data);
-
- md5.update(secret);
- sha1.update(secret);
-
- for(size_t i = 0; i != 48; ++i)
- md5.update(PAD_INNER);
- for(size_t i = 0; i != 40; ++i)
- sha1.update(PAD_INNER);
-
- SecureVector<byte> inner_md5 = md5.final(), inner_sha1 = sha1.final();
-
- md5.update(secret);
- sha1.update(secret);
- for(size_t i = 0; i != 48; ++i)
- md5.update(PAD_OUTER);
- for(size_t i = 0; i != 40; ++i)
- sha1.update(PAD_OUTER);
- md5.update(inner_md5);
- sha1.update(inner_sha1);
-
- SecureVector<byte> output;
- output += md5.final();
- output += sha1.final();
- return output;
- }
-
-}
diff --git a/src/ssl/tls_handshake_hash.h b/src/ssl/tls_handshake_hash.h
deleted file mode 100644
index cea612a71..000000000
--- a/src/ssl/tls_handshake_hash.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-* TLS Handshake Hash
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_HASH_H__
-#define BOTAN_TLS_HANDSHAKE_HASH_H__
-
-#include <botan/secmem.h>
-
-namespace Botan {
-
-using namespace Botan;
-
-/**
-* TLS Handshake Hash
-*/
-class HandshakeHash
- {
- public:
- void update(const byte in[], size_t length)
- { data += std::make_pair(in, length); }
-
- void update(const MemoryRegion<byte>& in)
- { data += in; }
-
- void update(byte in)
- { data.push_back(in); }
-
- SecureVector<byte> final();
- SecureVector<byte> final_ssl3(const MemoryRegion<byte>&);
- private:
- SecureVector<byte> data;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_magic.h b/src/ssl/tls_magic.h
deleted file mode 100644
index 00898738e..000000000
--- a/src/ssl/tls_magic.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
-* SSL/TLS Protocol Constants
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_PROTOCOL_MAGIC_H__
-#define BOTAN_TLS_PROTOCOL_MAGIC_H__
-
-namespace Botan {
-
-/**
-* Protocol Constants for SSL/TLS
-*/
-enum Size_Limits {
- MAX_PLAINTEXT_SIZE = 16*1024,
- MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024,
- MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024
-};
-
-enum Version_Code {
- NO_VERSION_SET = 0x0000,
- SSL_V3 = 0x0300,
- TLS_V10 = 0x0301,
- TLS_V11 = 0x0302
-};
-
-enum Connection_Side { CLIENT, SERVER };
-
-enum Record_Type {
- CONNECTION_CLOSED = 0,
-
- CHANGE_CIPHER_SPEC = 20,
- ALERT = 21,
- HANDSHAKE = 22,
- APPLICATION_DATA = 23
-};
-
-enum Handshake_Type {
- HELLO_REQUEST = 0,
- CLIENT_HELLO = 1,
- CLIENT_HELLO_SSLV2 = 255, // not a wire value
- SERVER_HELLO = 2,
- CERTIFICATE = 11,
- SERVER_KEX = 12,
- CERTIFICATE_REQUEST = 13,
- SERVER_HELLO_DONE = 14,
- CERTIFICATE_VERIFY = 15,
- CLIENT_KEX = 16,
- FINISHED = 20,
-
- HANDSHAKE_CCS = 100,
- HANDSHAKE_NONE = 101
-};
-
-enum Alert_Level {
- WARNING = 1,
- FATAL = 2
-};
-
-enum Alert_Type {
- CLOSE_NOTIFY = 0,
- UNEXPECTED_MESSAGE = 10,
- BAD_RECORD_MAC = 20,
- DECRYPTION_FAILED = 21,
- RECORD_OVERFLOW = 22,
- DECOMPRESSION_FAILURE = 30,
- HANDSHAKE_FAILURE = 40,
- BAD_CERTIFICATE = 42,
- UNSUPPORTED_CERTIFICATE = 43,
- CERTIFICATE_REVOKED = 44,
- CERTIFICATE_EXPIRED = 45,
- CERTIFICATE_UNKNOWN = 46,
- ILLEGAL_PARAMETER = 47,
- UNKNOWN_CA = 48,
- ACCESS_DENIED = 49,
- DECODE_ERROR = 50,
- DECRYPT_ERROR = 51,
- EXPORT_RESTRICTION = 60,
- PROTOCOL_VERSION = 70,
- INSUFFICIENT_SECURITY = 71,
- INTERNAL_ERROR = 80,
- USER_CANCELED = 90,
- NO_RENEGOTIATION = 100,
-
- UNKNOWN_PSK_IDENTITY = 115,
-
- NO_ALERT_TYPE = 0xFFFF
-};
-
-enum Certificate_Type {
- RSA_CERT = 1,
- DSS_CERT = 2,
- DH_RSA_CERT = 3,
- DH_DSS_CERT = 4
-};
-
-enum Ciphersuite_Code {
- TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
- TLS_RSA_WITH_RC4_128_SHA = 0x0005,
-
- TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
- TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F,
- TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035,
- TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
- TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
- TLS_RSA_WITH_SEED_CBC_SHA = 0x0096,
-
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
- TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099,
-
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
- TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A,
-
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
-
- TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028
-};
-
-/*
-* Form of the ciphersuites broken down by field instead of
-* being randomly assigned codepoints.
-*/
-enum TLS_Ciphersuite_Algos {
- TLS_ALGO_SIGNER_MASK = 0xFF000000,
- TLS_ALGO_SIGNER_ANON = 0x01000000,
- TLS_ALGO_SIGNER_RSA = 0x02000000,
- TLS_ALGO_SIGNER_DSA = 0x03000000,
- TLS_ALGO_SIGNER_ECDSA = 0x04000000,
-
- TLS_ALGO_KEYEXCH_MASK = 0x00FF0000,
- TLS_ALGO_KEYEXCH_NOKEX = 0x00010000,
- TLS_ALGO_KEYEXCH_RSA = 0x00020000,
- TLS_ALGO_KEYEXCH_DH = 0x00030000,
- TLS_ALGO_KEYEXCH_ECDH = 0x00040000,
-
- TLS_ALGO_MAC_MASK = 0x0000FF00,
- TLS_ALGO_MAC_MD5 = 0x00000100,
- TLS_ALGO_MAC_SHA1 = 0x00000200,
- TLS_ALGO_MAC_SHA256 = 0x00000300,
- TLS_ALGO_MAC_SHA384 = 0x00000400,
-
- TLS_ALGO_CIPHER_MASK = 0x000000FF,
- TLS_ALGO_CIPHER_RC4_128 = 0x00000001,
- TLS_ALGO_CIPHER_3DES_CBC = 0x00000002,
- TLS_ALGO_CIPHER_AES128_CBC = 0x00000003,
- TLS_ALGO_CIPHER_AES256_CBC = 0x00000004,
- TLS_ALGO_CIPHER_SEED_CBC = 0x00000005
-};
-
-enum Compression_Algo {
- NO_COMPRESSION = 0x00
-};
-
-enum TLS_Handshake_Extension_Type {
- TLSEXT_SERVER_NAME_INDICATION = 0,
- TLSEXT_MAX_FRAGMENT_LENGTH = 1,
- TLSEXT_CLIENT_CERT_URL = 2,
- TLSEXT_TRUSTED_CA_KEYS = 3,
- TLSEXT_TRUNCATED_HMAC = 4,
-
- TLSEXT_USABLE_ELLIPTIC_CURVES = 10,
- TLSEXT_EC_POINT_FORMATS = 11,
-
- TLSEXT_SRP_IDENTIFIER = 12,
-
- TLSEXT_CERTIFICATE_TYPES = 9,
- TLSEXT_SESSION_TICKET = 35
-};
-
-}
-
-#endif
diff --git a/src/ssl/tls_messages.h b/src/ssl/tls_messages.h
deleted file mode 100644
index e7eaa56e1..000000000
--- a/src/ssl/tls_messages.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
-* TLS Messages
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_MESSAGES_H__
-#define BOTAN_TLS_MESSAGES_H__
-
-#include <botan/tls_record.h>
-#include <botan/internal/tls_handshake_hash.h>
-#include <botan/tls_policy.h>
-#include <botan/bigint.h>
-#include <botan/pkcs8.h>
-#include <botan/x509cert.h>
-#include <vector>
-
-namespace Botan {
-
-/**
-* TLS Handshake Message Base Class
-*/
-class HandshakeMessage
- {
- public:
- void send(Record_Writer&, HandshakeHash&) const;
-
- virtual Handshake_Type type() const = 0;
-
- virtual ~HandshakeMessage() {}
- private:
- HandshakeMessage& operator=(const HandshakeMessage&) { return (*this); }
- virtual SecureVector<byte> serialize() const = 0;
- virtual void deserialize(const MemoryRegion<byte>&) = 0;
- };
-
-/**
-* Client Hello Message
-*/
-class Client_Hello : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return CLIENT_HELLO; }
- Version_Code version() const { return c_version; }
- const SecureVector<byte>& session_id() const { return sess_id; }
- std::vector<u16bit> ciphersuites() const { return suites; }
- std::vector<byte> compression_algos() const { return comp_algos; }
-
- const SecureVector<byte>& random() const { return c_random; }
-
- std::string hostname() const { return requested_hostname; }
-
- std::string srp_identifier() const { return requested_srp_id; }
-
- bool offered_suite(u16bit) const;
-
- Client_Hello(RandomNumberGenerator& rng,
- Record_Writer&, const TLS_Policy&, HandshakeHash&);
-
- Client_Hello(const MemoryRegion<byte>& buf,
- Handshake_Type type)
- {
- if(type == CLIENT_HELLO)
- deserialize(buf);
- else
- deserialize_sslv2(buf);
- }
-
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
- void deserialize_sslv2(const MemoryRegion<byte>&);
-
- Version_Code c_version;
- SecureVector<byte> sess_id, c_random;
- std::vector<u16bit> suites;
- std::vector<byte> comp_algos;
- std::string requested_hostname;
- std::string requested_srp_id;
- };
-
-/**
-* Client Key Exchange Message
-*/
-class Client_Key_Exchange : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return CLIENT_KEX; }
-
- SecureVector<byte> pre_master_secret() const;
-
- SecureVector<byte> pre_master_secret(RandomNumberGenerator& rng,
- const Private_Key* key,
- Version_Code version);
-
- Client_Key_Exchange(RandomNumberGenerator& rng,
- Record_Writer& output,
- HandshakeHash& hash,
- const Public_Key* my_key,
- Version_Code using_version,
- Version_Code pref_version);
-
- Client_Key_Exchange(const MemoryRegion<byte>& buf,
- const CipherSuite& suite,
- Version_Code using_version);
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
-
- SecureVector<byte> key_material, pre_master;
- bool include_length;
- };
-
-/**
-* Certificate Message
-*/
-class Certificate : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return CERTIFICATE; }
- std::vector<X509_Certificate> cert_chain() const { return certs; }
-
- Certificate(Record_Writer&, const std::vector<X509_Certificate>&,
- HandshakeHash&);
- Certificate(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
- std::vector<X509_Certificate> certs;
- };
-
-/**
-* Certificate Request Message
-*/
-class Certificate_Req : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return CERTIFICATE_REQUEST; }
-
- std::vector<Certificate_Type> acceptable_types() const { return types; }
- std::vector<X509_DN> acceptable_CAs() const { return names; }
-
- /* TODO
- Certificate_Req(Record_Writer&, HandshakeHash&,
- const X509_Certificate&);
- */
- Certificate_Req(Record_Writer&, HandshakeHash&,
- const std::vector<X509_Certificate>&);
-
- Certificate_Req(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
-
- std::vector<X509_DN> names;
- std::vector<Certificate_Type> types;
- };
-
-/**
-* Certificate Verify Message
-*/
-class Certificate_Verify : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return CERTIFICATE_VERIFY; }
-
- bool verify(const X509_Certificate&, HandshakeHash&);
-
- Certificate_Verify(RandomNumberGenerator& rng,
- Record_Writer&, HandshakeHash&,
- const Private_Key*);
-
- Certificate_Verify(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
-
- SecureVector<byte> signature;
- };
-
-/**
-* Finished Message
-*/
-class Finished : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return FINISHED; }
-
- bool verify(const MemoryRegion<byte>&, Version_Code,
- const HandshakeHash&, Connection_Side);
-
- Finished(Record_Writer&, Version_Code, Connection_Side,
- const MemoryRegion<byte>&, HandshakeHash&);
- Finished(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
-
- SecureVector<byte> compute_verify(const MemoryRegion<byte>&,
- HandshakeHash, Connection_Side,
- Version_Code);
-
- Connection_Side side;
- SecureVector<byte> verification_data;
- };
-
-/**
-* Hello Request Message
-*/
-class Hello_Request : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return HELLO_REQUEST; }
-
- Hello_Request(Record_Writer&);
- Hello_Request(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
- };
-
-/**
-* Server Hello Message
-*/
-class Server_Hello : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return SERVER_HELLO; }
- Version_Code version() { return s_version; }
- const SecureVector<byte>& session_id() const { return sess_id; }
- u16bit ciphersuite() const { return suite; }
- byte compression_algo() const { return comp_algo; }
-
- const SecureVector<byte>& random() const { return s_random; }
-
- Server_Hello(RandomNumberGenerator& rng,
- Record_Writer&, const TLS_Policy&,
- const std::vector<X509_Certificate>&,
- const Client_Hello&, Version_Code, HandshakeHash&);
-
- Server_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
-
- Version_Code s_version;
- SecureVector<byte> sess_id, s_random;
- u16bit suite;
- byte comp_algo;
- };
-
-/**
-* Server Key Exchange Message
-*/
-class Server_Key_Exchange : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return SERVER_KEX; }
- Public_Key* key() const;
-
- bool verify(const X509_Certificate&, const MemoryRegion<byte>&,
- const MemoryRegion<byte>&) const;
-
- Server_Key_Exchange(RandomNumberGenerator& rng,
- Record_Writer&, const Public_Key*,
- const Private_Key*, const MemoryRegion<byte>&,
- const MemoryRegion<byte>&, HandshakeHash&);
-
- Server_Key_Exchange(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- SecureVector<byte> serialize_params() const;
- void deserialize(const MemoryRegion<byte>&);
-
- std::vector<BigInt> params;
- SecureVector<byte> signature;
- };
-
-/**
-* Server Hello Done Message
-*/
-class Server_Hello_Done : public HandshakeMessage
- {
- public:
- Handshake_Type type() const { return SERVER_HELLO_DONE; }
-
- Server_Hello_Done(Record_Writer&, HandshakeHash&);
- Server_Hello_Done(const MemoryRegion<byte>& buf) { deserialize(buf); }
- private:
- SecureVector<byte> serialize() const;
- void deserialize(const MemoryRegion<byte>&);
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_policy.cpp b/src/ssl/tls_policy.cpp
deleted file mode 100644
index b73ff7850..000000000
--- a/src/ssl/tls_policy.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-* Policies for TLS
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_policy.h>
-#include <botan/tls_exceptn.h>
-
-namespace Botan {
-
-/*
-* Return allowed ciphersuites
-*/
-std::vector<u16bit> TLS_Policy::ciphersuites() const
- {
- return suite_list(allow_static_rsa(), allow_edh_rsa(), allow_edh_dsa());
- }
-
-/*
-* Return allowed ciphersuites
-*/
-std::vector<u16bit> TLS_Policy::suite_list(bool use_rsa,
- bool use_edh_rsa,
- bool use_edh_dsa) const
- {
- std::vector<u16bit> suites;
-
- if(use_edh_dsa)
- {
- suites.push_back(TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
- suites.push_back(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_DHE_DSS_WITH_SEED_CBC_SHA);
- }
-
- if(use_edh_rsa)
- {
- suites.push_back(TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
- suites.push_back(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_DHE_RSA_WITH_SEED_CBC_SHA);
- }
-
- if(use_rsa)
- {
- suites.push_back(TLS_RSA_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_AES_128_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_SEED_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_RC4_128_SHA);
- suites.push_back(TLS_RSA_WITH_RC4_128_MD5);
- }
-
- if(suites.size() == 0)
- throw TLS_Exception(INTERNAL_ERROR,
- "TLS_Policy error: All ciphersuites disabled");
-
- return suites;
- }
-
-/*
-* Return allowed compression algorithms
-*/
-std::vector<byte> TLS_Policy::compression() const
- {
- std::vector<byte> algs;
- algs.push_back(NO_COMPRESSION);
- return algs;
- }
-
-/*
-* Choose which ciphersuite to use
-*/
-u16bit TLS_Policy::choose_suite(const std::vector<u16bit>& c_suites,
- bool have_rsa,
- bool have_dsa) const
- {
- bool use_static_rsa = allow_static_rsa() && have_rsa;
- bool use_edh_rsa = allow_edh_rsa() && have_rsa;
- bool use_edh_dsa = allow_edh_dsa() && have_dsa;
-
- std::vector<u16bit> s_suites = suite_list(use_static_rsa, use_edh_rsa,
- use_edh_dsa);
-
- for(size_t i = 0; i != s_suites.size(); ++i)
- for(size_t j = 0; j != c_suites.size(); ++j)
- if(s_suites[i] == c_suites[j])
- return s_suites[i];
-
- return 0;
- }
-
-/*
-* Choose which compression algorithm to use
-*/
-byte TLS_Policy::choose_compression(const std::vector<byte>& c_comp) const
- {
- std::vector<byte> s_comp = compression();
-
- for(size_t i = 0; i != s_comp.size(); ++i)
- for(size_t j = 0; j != c_comp.size(); ++j)
- if(s_comp[i] == c_comp[j])
- return s_comp[i];
-
- return NO_COMPRESSION;
- }
-
-/*
-* Return the group to use for empheral DH
-*/
-DL_Group TLS_Policy::dh_group() const
- {
- return DL_Group("modp/ietf/1024");
- }
-
-}
diff --git a/src/ssl/tls_policy.h b/src/ssl/tls_policy.h
deleted file mode 100644
index 461164d2f..000000000
--- a/src/ssl/tls_policy.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-* Policies
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_POLICY_H__
-#define BOTAN_TLS_POLICY_H__
-
-#include <botan/tls_magic.h>
-#include <botan/x509cert.h>
-#include <botan/dl_group.h>
-#include <vector>
-
-namespace Botan {
-
-/**
-* TLS Policy Base Class
-* Inherit and overload as desired to suite local policy concerns
-*/
-class BOTAN_DLL TLS_Policy
- {
- public:
- std::vector<u16bit> ciphersuites() const;
- virtual std::vector<byte> compression() const;
-
- virtual u16bit choose_suite(const std::vector<u16bit>& client_suites,
- bool rsa_ok,
- bool dsa_ok) const;
-
- virtual byte choose_compression(const std::vector<byte>& client) const;
-
- virtual bool allow_static_rsa() const { return true; }
- virtual bool allow_edh_rsa() const { return true; }
- virtual bool allow_edh_dsa() const { return true; }
- virtual bool require_client_auth() const { return false; }
-
- virtual DL_Group dh_group() const;
- virtual size_t rsa_export_keysize() const { return 512; }
-
- /*
- * @return the minimum version that we will negotiate
- */
- virtual Version_Code min_version() const { return SSL_V3; }
-
- /*
- * @return the version we would prefer to negotiate
- */
- virtual Version_Code pref_version() const { return TLS_V11; }
-
- virtual bool check_cert(const std::vector<X509_Certificate>& cert_chain) const = 0;
-
- virtual ~TLS_Policy() {}
- private:
- virtual std::vector<u16bit> suite_list(bool use_rsa,
- bool use_edh_rsa,
- bool use_edh_dsa) const;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_record.h b/src/ssl/tls_record.h
deleted file mode 100644
index 09fd921c6..000000000
--- a/src/ssl/tls_record.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-* TLS Record Handling
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_RECORDS_H__
-#define BOTAN_TLS_RECORDS_H__
-
-#include <botan/tls_session_key.h>
-#include <botan/tls_suites.h>
-#include <botan/pipe.h>
-#include <botan/mac.h>
-#include <botan/secqueue.h>
-#include <vector>
-
-#if defined(BOTAN_USE_STD_TR1)
-
-#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
- #include <functional>
-#else
- #include <tr1/functional>
-#endif
-
-#elif defined(BOTAN_USE_BOOST_TR1)
- #include <boost/tr1/functional.hpp>
-#else
- #error "No TR1 library defined for use"
-#endif
-
-namespace Botan {
-
-using namespace std::tr1::placeholders;
-
-/**
-* TLS Record Writer
-*/
-class BOTAN_DLL Record_Writer
- {
- public:
- void send(byte type, const byte input[], size_t length);
- void send(byte type, byte val) { send(type, &val, 1); }
-
- void flush();
-
- void alert(Alert_Level, Alert_Type);
-
- void set_keys(const CipherSuite&, const SessionKeys&, Connection_Side);
-
- void set_version(Version_Code);
-
- void reset();
-
- Record_Writer(std::tr1::function<void (const byte[], size_t)> output_fn);
-
- ~Record_Writer() { delete mac; }
- private:
- void send_record(byte type, const byte input[], size_t length);
- void send_record(byte type, byte major, byte minor,
- const byte input[], size_t length);
-
- std::tr1::function<void (const byte[], size_t)> output_fn;
- Pipe cipher;
- MessageAuthenticationCode* mac;
-
- SecureVector<byte> buffer;
- size_t buf_pos;
-
- size_t block_size, mac_size, iv_size;
-
- u64bit seq_no;
- byte major, minor, buf_type;
- };
-
-/**
-* TLS Record Reader
-*/
-class BOTAN_DLL Record_Reader
- {
- public:
- void add_input(const byte input[], size_t input_size);
-
- /**
- * @param msg_type (output variable)
- * @param buffer (output variable)
- * @return Number of bytes still needed (minimum), or 0 if success
- */
- size_t get_record(byte& msg_type,
- MemoryRegion<byte>& buffer);
-
- SecureVector<byte> get_record(byte& msg_type);
-
- void set_keys(const CipherSuite& suite,
- const SessionKeys& keys,
- Connection_Side side);
-
- void set_version(Version_Code version);
-
- void reset();
-
- Record_Reader() { mac = 0; reset(); }
-
- ~Record_Reader() { delete mac; }
- private:
- SecureQueue input_queue;
-
- Pipe cipher;
- MessageAuthenticationCode* mac;
- size_t block_size, mac_size, iv_size;
- u64bit seq_no;
- byte major, minor;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp
deleted file mode 100644
index 8964be3d7..000000000
--- a/src/ssl/tls_server.cpp
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
-* TLS Server
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_server.h>
-#include <botan/internal/tls_alerts.h>
-#include <botan/internal/tls_state.h>
-#include <botan/loadstor.h>
-#include <botan/rsa.h>
-#include <botan/dh.h>
-
-namespace Botan {
-
-namespace {
-
-/*
-* Choose what version to respond with
-*/
-Version_Code choose_version(Version_Code client, Version_Code minimum)
- {
- if(client < minimum)
- throw TLS_Exception(PROTOCOL_VERSION,
- "Client version is unacceptable by policy");
-
- if(client == SSL_V3 || client == TLS_V10 || client == TLS_V11)
- return client;
- return TLS_V11;
- }
-
-// FIXME: checks are wrong for session reuse (add a flag for that)
-/*
-* Verify the state transition is allowed
-*/
-void server_check_state(Handshake_Type new_msg, Handshake_State* state)
- {
- class State_Transition_Error : public Unexpected_Message
- {
- public:
- State_Transition_Error(const std::string& err) :
- Unexpected_Message("State transition error from " + err) {}
- };
-
- if(new_msg == CLIENT_HELLO || new_msg == CLIENT_HELLO_SSLV2)
- {
- if(state->server_hello)
- throw State_Transition_Error("ClientHello");
- }
- else if(new_msg == CERTIFICATE)
- {
- if(!state->do_client_auth || !state->cert_req ||
- !state->server_hello_done || state->client_kex)
- throw State_Transition_Error("ClientCertificate");
- }
- else if(new_msg == CLIENT_KEX)
- {
- if(!state->server_hello_done || state->client_verify ||
- state->got_client_ccs)
- throw State_Transition_Error("ClientKeyExchange");
- }
- else if(new_msg == CERTIFICATE_VERIFY)
- {
- if(!state->cert_req || !state->client_certs || !state->client_kex ||
- state->got_client_ccs)
- throw State_Transition_Error("CertificateVerify");
- }
- else if(new_msg == HANDSHAKE_CCS)
- {
- if(!state->client_kex || state->client_finished)
- throw State_Transition_Error("ClientChangeCipherSpec");
- }
- else if(new_msg == FINISHED)
- {
- if(!state->got_client_ccs)
- throw State_Transition_Error("ClientFinished");
- }
- else
- throw Unexpected_Message("Unexpected message in handshake");
- }
-
-}
-
-/*
-* TLS Server Constructor
-*/
-TLS_Server::TLS_Server(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,
- const X509_Certificate& cert,
- const Private_Key& cert_key) :
- input_fn(input_fn),
- policy(policy),
- rng(rng),
- writer(output_fn)
- {
- state = 0;
-
- cert_chain.push_back(cert);
- private_key = PKCS8::copy_key(cert_key, rng);
-
- try {
- active = false;
- writer.set_version(TLS_V10);
- do_handshake();
- active = true;
- }
- catch(std::exception& e)
- {
- if(state)
- {
- delete state;
- state = 0;
- }
-
- writer.alert(FATAL, HANDSHAKE_FAILURE);
- throw Stream_IO_Error(std::string("TLS_Server: Handshake failed: ") +
- e.what());
- }
- }
-
-/*
-* TLS Server Destructor
-*/
-TLS_Server::~TLS_Server()
- {
- close();
- delete private_key;
- delete state;
- }
-
-/*
-* Return the peer's certificate chain
-*/
-std::vector<X509_Certificate> TLS_Server::peer_cert_chain() const
- {
- return peer_certs;
- }
-
-/*
-* Write to a TLS connection
-*/
-void TLS_Server::write(const byte buf[], size_t length)
- {
- if(!active)
- throw Internal_Error("TLS_Server::write called while closed");
-
- writer.send(APPLICATION_DATA, buf, length);
- }
-
-/*
-* Read from a TLS connection
-*/
-size_t TLS_Server::read(byte out[], size_t length)
- {
- if(!active)
- throw Internal_Error("TLS_Server::read called while closed");
-
- writer.flush();
-
- while(read_buf.size() == 0)
- {
- state_machine();
- if(active == false)
- break;
- }
-
- size_t got = std::min<size_t>(read_buf.size(), length);
- read_buf.read(out, got);
- return got;
- }
-
-/*
-* Check connection status
-*/
-bool TLS_Server::is_closed() const
- {
- if(!active)
- return true;
- return false;
- }
-
-/*
-* Close a TLS connection
-*/
-void TLS_Server::close()
- {
- close(WARNING, CLOSE_NOTIFY);
- }
-
-/*
-* Close a TLS connection
-*/
-void TLS_Server::close(Alert_Level level, Alert_Type alert_code)
- {
- if(active)
- {
- try {
- active = false;
- writer.alert(level, alert_code);
- writer.flush();
- }
- catch(...) {}
- }
- }
-
-/*
-* Iterate the TLS state machine
-*/
-void TLS_Server::state_machine()
- {
- byte rec_type = CONNECTION_CLOSED;
- SecureVector<byte> record(1024);
-
- size_t bytes_needed = reader.get_record(rec_type, record);
-
- while(bytes_needed)
- {
- size_t to_get = std::min<size_t>(record.size(), bytes_needed);
- size_t got = input_fn(&record[0], to_get);
-
- if(got == 0)
- {
- rec_type = CONNECTION_CLOSED;
- break;
- }
-
- reader.add_input(&record[0], got);
-
- bytes_needed = reader.get_record(rec_type, record);
- }
-
- if(rec_type == CONNECTION_CLOSED)
- {
- active = false;
- reader.reset();
- writer.reset();
- }
- else if(rec_type == APPLICATION_DATA)
- {
- if(active)
- read_buf.write(&record[0], record.size());
- else
- throw Unexpected_Message("Application data before handshake done");
- }
- else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC)
- read_handshake(rec_type, record);
- else if(rec_type == ALERT)
- {
- Alert alert(record);
-
- if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY)
- {
- if(alert.type() == CLOSE_NOTIFY)
- writer.alert(WARNING, CLOSE_NOTIFY);
-
- reader.reset();
- writer.reset();
- active = false;
- }
- }
- else
- throw Unexpected_Message("Unknown message type received");
- }
-
-/*
-* Split up and process handshake messages
-*/
-void TLS_Server::read_handshake(byte rec_type,
- const MemoryRegion<byte>& rec_buf)
- {
- if(rec_type == HANDSHAKE)
- {
- if(!state)
- state = new Handshake_State;
- state->queue.write(&rec_buf[0], rec_buf.size());
- }
-
- while(true)
- {
- Handshake_Type type = HANDSHAKE_NONE;
- SecureVector<byte> contents;
-
- if(rec_type == HANDSHAKE)
- {
- if(state->queue.size() >= 4)
- {
- byte head[4] = { 0 };
- state->queue.peek(head, 4);
-
- const size_t length = make_u32bit(0, head[1], head[2], head[3]);
-
- if(state->queue.size() >= length + 4)
- {
- type = static_cast<Handshake_Type>(head[0]);
- contents.resize(length);
- state->queue.read(head, 4);
- state->queue.read(&contents[0], contents.size());
- }
- }
- }
- else if(rec_type == CHANGE_CIPHER_SPEC)
- {
- if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1)
- type = HANDSHAKE_CCS;
- else
- throw Decoding_Error("Malformed ChangeCipherSpec message");
- }
- else
- throw Decoding_Error("Unknown message type in handshake processing");
-
- if(type == HANDSHAKE_NONE)
- break;
-
- process_handshake_msg(type, contents);
-
- if(type == HANDSHAKE_CCS || !state)
- break;
- }
- }
-
-/*
-* Process a handshake message
-*/
-void TLS_Server::process_handshake_msg(Handshake_Type type,
- const MemoryRegion<byte>& contents)
- {
- rng.add_entropy(&contents[0], contents.size());
-
- if(state == 0)
- throw Unexpected_Message("Unexpected handshake message");
-
- if(type != HANDSHAKE_CCS && type != FINISHED)
- {
- if(type != CLIENT_HELLO_SSLV2)
- {
- state->hash.update(static_cast<byte>(type));
-
- const size_t record_length = contents.size();
- for(size_t i = 0; i != 3; i++)
- state->hash.update(get_byte<u32bit>(i+1, record_length));
- }
-
- state->hash.update(contents);
- }
-
- if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
- {
- server_check_state(type, state);
-
- state->client_hello = new Client_Hello(contents, type);
-
- client_requested_hostname = state->client_hello->hostname();
-
- state->version = choose_version(state->client_hello->version(),
- policy.min_version());
-
- writer.set_version(state->version);
- reader.set_version(state->version);
-
- state->server_hello = new Server_Hello(rng, writer,
- policy, cert_chain,
- *(state->client_hello),
- state->version, state->hash);
-
- state->suite = CipherSuite(state->server_hello->ciphersuite());
-
- if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON)
- {
- // FIXME: should choose certs based on sig type
- state->server_certs = new Certificate(writer, cert_chain,
- state->hash);
- }
-
- state->kex_priv = PKCS8::copy_key(*private_key, rng);
- if(state->suite.kex_type() != TLS_ALGO_KEYEXCH_NOKEX)
- {
- if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_RSA)
- {
- state->kex_priv = new RSA_PrivateKey(rng,
- policy.rsa_export_keysize());
- }
- else if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_DH)
- {
- state->kex_priv = new DH_PrivateKey(rng, policy.dh_group());
- }
- else
- throw Internal_Error("TLS_Server: Unknown ciphersuite kex type");
-
- state->server_kex =
- new Server_Key_Exchange(rng, writer,
- state->kex_priv, private_key,
- state->client_hello->random(),
- state->server_hello->random(),
- state->hash);
- }
-
- if(policy.require_client_auth())
- {
- state->do_client_auth = true;
- throw Internal_Error("Client auth not implemented");
- // FIXME: send client auth request here
- }
-
- state->server_hello_done = new Server_Hello_Done(writer, state->hash);
- }
- else if(type == CERTIFICATE)
- {
- server_check_state(type, state);
- // FIXME: process this
- }
- else if(type == CLIENT_KEX)
- {
- server_check_state(type, state);
-
- state->client_kex = new Client_Key_Exchange(contents, state->suite,
- state->version);
-
- SecureVector<byte> pre_master =
- state->client_kex->pre_master_secret(rng, state->kex_priv,
- state->server_hello->version());
-
- state->keys = SessionKeys(state->suite, state->version, pre_master,
- state->client_hello->random(),
- state->server_hello->random());
- }
- else if(type == CERTIFICATE_VERIFY)
- {
- server_check_state(type, state);
- // FIXME: process this
- }
- else if(type == HANDSHAKE_CCS)
- {
- server_check_state(type, state);
-
- reader.set_keys(state->suite, state->keys, SERVER);
- state->got_client_ccs = true;
- }
- else if(type == FINISHED)
- {
- server_check_state(type, state);
-
- state->client_finished = new Finished(contents);
-
- if(!state->client_finished->verify(state->keys.master_secret(),
- state->version, state->hash, CLIENT))
- throw TLS_Exception(DECRYPT_ERROR,
- "Finished message didn't verify");
-
- state->hash.update(static_cast<byte>(type));
-
- const size_t record_length = contents.size();
- for(size_t i = 0; i != 3; i++)
- state->hash.update(get_byte<u32bit>(i+1, record_length));
-
- state->hash.update(contents);
-
- writer.send(CHANGE_CIPHER_SPEC, 1);
- writer.flush();
-
- writer.set_keys(state->suite, state->keys, SERVER);
-
- state->server_finished = new Finished(writer, state->version, SERVER,
- state->keys.master_secret(),
- state->hash);
-
- delete state;
- state = 0;
- active = true;
- }
- else
- throw Unexpected_Message("Unknown handshake message received");
- }
-
-/*
-* Perform a server-side TLS handshake
-*/
-void TLS_Server::do_handshake()
- {
- while(true)
- {
- if(active && !state)
- break;
-
- state_machine();
-
- if(!active && !state)
- throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Server: Handshake failed");
- }
- }
-
-}
diff --git a/src/ssl/tls_server.h b/src/ssl/tls_server.h
deleted file mode 100644
index a6b0f9cb4..000000000
--- a/src/ssl/tls_server.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-* TLS Server
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SERVER_H__
-#define BOTAN_TLS_SERVER_H__
-
-#include <botan/tls_connection.h>
-#include <botan/tls_record.h>
-#include <botan/tls_policy.h>
-#include <vector>
-
-namespace Botan {
-
-/**
-* TLS Server
-*/
-class BOTAN_DLL TLS_Server : public TLS_Connection
- {
- public:
- size_t read(byte buf[], size_t buf_len);
- void write(const byte buf[], size_t buf_len);
-
- std::vector<X509_Certificate> peer_cert_chain() const;
-
- std::string requested_hostname() const
- { return client_requested_hostname; }
-
- void close();
- bool is_closed() const;
-
- /*
- * FIXME: support cert chains (!)
- * FIXME: support anonymous servers
- */
- TLS_Server(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,
- const X509_Certificate& cert,
- const Private_Key& cert_key);
-
- ~TLS_Server();
- private:
- void close(Alert_Level, Alert_Type);
-
- void do_handshake();
- void state_machine();
- void read_handshake(byte, const MemoryRegion<byte>&);
-
- void process_handshake_msg(Handshake_Type, const MemoryRegion<byte>&);
-
- std::tr1::function<size_t (byte[], size_t)> input_fn;
-
- const TLS_Policy& policy;
- RandomNumberGenerator& rng;
-
- Record_Writer writer;
- Record_Reader reader;
-
- // FIXME: rename to match TLS_Client
- std::vector<X509_Certificate> cert_chain, peer_certs;
- Private_Key* private_key;
-
- class Handshake_State* state;
- SecureVector<byte> session_id;
- SecureQueue read_buf;
- std::string client_requested_hostname;
- bool active;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_session_key.cpp b/src/ssl/tls_session_key.cpp
deleted file mode 100644
index 7c75d1758..000000000
--- a/src/ssl/tls_session_key.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-* TLS Session Key
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_session_key.h>
-#include <botan/prf_ssl3.h>
-#include <botan/prf_tls.h>
-#include <botan/lookup.h>
-
-namespace Botan {
-
-/**
-* Return the client cipher key
-*/
-SymmetricKey SessionKeys::client_cipher_key() const
- {
- return c_cipher;
- }
-
-/**
-* Return the server cipher key
-*/
-SymmetricKey SessionKeys::server_cipher_key() const
- {
- return s_cipher;
- }
-
-/**
-* Return the client MAC key
-*/
-SymmetricKey SessionKeys::client_mac_key() const
- {
- return c_mac;
- }
-
-/**
-* Return the server MAC key
-*/
-SymmetricKey SessionKeys::server_mac_key() const
- {
- return s_mac;
- }
-
-/**
-* Return the client cipher IV
-*/
-InitializationVector SessionKeys::client_iv() const
- {
- return c_iv;
- }
-
-/**
-* Return the server cipher IV
-*/
-InitializationVector SessionKeys::server_iv() const
- {
- return s_iv;
- }
-
-/**
-* Return the TLS master secret
-*/
-SecureVector<byte> SessionKeys::master_secret() const
- {
- return master_sec;
- }
-
-/**
-* Generate SSLv3 session keys
-*/
-SymmetricKey SessionKeys::ssl3_keygen(size_t prf_gen,
- const MemoryRegion<byte>& pre_master,
- const MemoryRegion<byte>& client_random,
- const MemoryRegion<byte>& server_random)
- {
- SSL3_PRF prf;
-
- SecureVector<byte> salt;
- salt += client_random;
- salt += server_random;
-
- master_sec = prf.derive_key(48, pre_master, salt);
-
- salt.clear();
- salt += server_random;
- salt += client_random;
-
- return prf.derive_key(prf_gen, master_sec, salt);
- }
-
-/**
-* Generate TLS 1.0 session keys
-*/
-SymmetricKey SessionKeys::tls1_keygen(size_t prf_gen,
- const MemoryRegion<byte>& pre_master,
- const MemoryRegion<byte>& client_random,
- const MemoryRegion<byte>& server_random)
- {
- const byte MASTER_SECRET_MAGIC[] = {
- 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65,
- 0x74 };
- const byte KEY_GEN_MAGIC[] = {
- 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F,
- 0x6E };
-
- TLS_PRF prf;
-
- SecureVector<byte> salt;
- salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC));
- salt += client_random;
- salt += server_random;
-
- master_sec = prf.derive_key(48, pre_master, salt);
-
- salt.clear();
- salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC));
- salt += server_random;
- salt += client_random;
-
- return prf.derive_key(prf_gen, master_sec, salt);
- }
-
-/**
-* SessionKeys Constructor
-*/
-SessionKeys::SessionKeys(const CipherSuite& suite, Version_Code version,
- const MemoryRegion<byte>& pre_master_secret,
- const MemoryRegion<byte>& c_random,
- const MemoryRegion<byte>& s_random)
- {
- if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11)
- throw Invalid_Argument("SessionKeys: Unknown version code");
-
- const size_t mac_keylen = output_length_of(suite.mac_algo());
- const size_t cipher_keylen = suite.cipher_keylen();
-
- size_t cipher_ivlen = 0;
- if(have_block_cipher(suite.cipher_algo()))
- cipher_ivlen = block_size_of(suite.cipher_algo());
-
- const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen);
-
- SymmetricKey keyblock = (version == SSL_V3) ?
- ssl3_keygen(prf_gen, pre_master_secret, c_random, s_random) :
- tls1_keygen(prf_gen, pre_master_secret, c_random, s_random);
-
- const byte* key_data = keyblock.begin();
-
- c_mac = SymmetricKey(key_data, mac_keylen);
- key_data += mac_keylen;
-
- s_mac = SymmetricKey(key_data, mac_keylen);
- key_data += mac_keylen;
-
- c_cipher = SymmetricKey(key_data, cipher_keylen);
- key_data += cipher_keylen;
-
- s_cipher = SymmetricKey(key_data, cipher_keylen);
- key_data += cipher_keylen;
-
- c_iv = InitializationVector(key_data, cipher_ivlen);
- key_data += cipher_ivlen;
-
- s_iv = InitializationVector(key_data, cipher_ivlen);
- }
-
-}
diff --git a/src/ssl/tls_session_key.h b/src/ssl/tls_session_key.h
deleted file mode 100644
index 51397984b..000000000
--- a/src/ssl/tls_session_key.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-* TLS Session Key
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SESSION_KEYS_H__
-#define BOTAN_TLS_SESSION_KEYS_H__
-
-#include <botan/tls_suites.h>
-#include <botan/tls_exceptn.h>
-#include <botan/symkey.h>
-
-namespace Botan {
-
-/**
-* TLS Session Keys
-*/
-class BOTAN_DLL SessionKeys
- {
- public:
- SymmetricKey client_cipher_key() const;
- SymmetricKey server_cipher_key() const;
-
- SymmetricKey client_mac_key() const;
- SymmetricKey server_mac_key() const;
-
- InitializationVector client_iv() const;
- InitializationVector server_iv() const;
-
- SecureVector<byte> master_secret() const;
-
- SessionKeys() {}
- SessionKeys(const CipherSuite&, Version_Code, const MemoryRegion<byte>&,
- const MemoryRegion<byte>&, const MemoryRegion<byte>&);
- private:
- SymmetricKey ssl3_keygen(size_t, const MemoryRegion<byte>&,
- const MemoryRegion<byte>&,
- const MemoryRegion<byte>&);
- SymmetricKey tls1_keygen(size_t, const MemoryRegion<byte>&,
- const MemoryRegion<byte>&,
- const MemoryRegion<byte>&);
-
- SecureVector<byte> master_sec;
- SymmetricKey c_cipher, s_cipher, c_mac, s_mac;
- InitializationVector c_iv, s_iv;
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_state.cpp b/src/ssl/tls_state.cpp
deleted file mode 100644
index 6aaf5e201..000000000
--- a/src/ssl/tls_state.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-* TLS Handshaking
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_state.h>
-
-namespace Botan {
-
-/**
-* Initialize the SSL/TLS Handshake State
-*/
-Handshake_State::Handshake_State()
- {
- client_hello = 0;
- server_hello = 0;
- server_certs = 0;
- server_kex = 0;
- cert_req = 0;
- server_hello_done = 0;
-
- client_certs = 0;
- client_kex = 0;
- client_verify = 0;
- client_finished = 0;
- server_finished = 0;
-
- kex_pub = 0;
- kex_priv = 0;
-
- do_client_auth = got_client_ccs = got_server_ccs = false;
- version = SSL_V3;
- }
-
-/**
-* Destroy the SSL/TLS Handshake State
-*/
-Handshake_State::~Handshake_State()
- {
- delete client_hello;
- delete server_hello;
- delete server_certs;
- delete server_kex;
- delete cert_req;
- delete server_hello_done;
-
- delete client_certs;
- delete client_kex;
- delete client_verify;
- delete client_finished;
- delete server_finished;
-
- delete kex_pub;
- delete kex_priv;
- }
-
-}
diff --git a/src/ssl/tls_state.h b/src/ssl/tls_state.h
deleted file mode 100644
index e2728198f..000000000
--- a/src/ssl/tls_state.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-* TLS Handshake State
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_H__
-#define BOTAN_TLS_HANDSHAKE_H__
-
-#include <botan/internal/tls_messages.h>
-#include <botan/secqueue.h>
-
-namespace Botan {
-
-/**
-* SSL/TLS Handshake State
-*/
-class Handshake_State
- {
- public:
- Client_Hello* client_hello;
- Server_Hello* server_hello;
- Certificate* server_certs;
- Server_Key_Exchange* server_kex;
- Certificate_Req* cert_req;
- Server_Hello_Done* server_hello_done;
-
- Certificate* client_certs;
- Client_Key_Exchange* client_kex;
- Certificate_Verify* client_verify;
- Finished* client_finished;
- Finished* server_finished;
-
- Public_Key* kex_pub;
- Private_Key* kex_priv;
-
- CipherSuite suite;
- SessionKeys keys;
- HandshakeHash hash;
-
- SecureQueue queue;
-
- Version_Code version;
- bool got_client_ccs, got_server_ccs, do_client_auth;
-
- Handshake_State();
- ~Handshake_State();
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_suites.cpp b/src/ssl/tls_suites.cpp
deleted file mode 100644
index 07cbec608..000000000
--- a/src/ssl/tls_suites.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
-* TLS Cipher Suites
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_suites.h>
-#include <botan/tls_exceptn.h>
-
-namespace Botan {
-
-/**
-* Convert an SSL/TLS ciphersuite to algorithm fields
-*/
-TLS_Ciphersuite_Algos CipherSuite::lookup_ciphersuite(u16bit suite)
- {
- if(suite == TLS_RSA_WITH_RC4_128_MD5)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_MD5 |
- TLS_ALGO_CIPHER_RC4_128);
-
- if(suite == TLS_RSA_WITH_RC4_128_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_RC4_128);
-
- if(suite == TLS_RSA_WITH_3DES_EDE_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_3DES_CBC);
-
- if(suite == TLS_RSA_WITH_AES_128_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_RSA_WITH_AES_256_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_RSA_WITH_SEED_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_SEED_CBC);
-
- if(suite == TLS_RSA_WITH_AES_128_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_RSA_WITH_AES_256_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_NOKEX |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_3DES_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_AES_128_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_SEED_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_SEED_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_AES_256_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_AES_128_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_AES_256_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_3DES_CBC);
-
- if(suite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_DHE_DSS_WITH_SEED_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_SEED_CBC);
-
- if(suite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_DH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_RC4_128_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_RC4_128);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_3DES_CBC);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA384 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_ECDHE_RSA_WITH_RC4_128_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_RC4_128);
-
- if(suite == TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_3DES_CBC);
-
- if(suite == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA1 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- if(suite == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA256 |
- TLS_ALGO_CIPHER_AES128_CBC);
-
- if(suite == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384)
- return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA |
- TLS_ALGO_KEYEXCH_ECDH |
- TLS_ALGO_MAC_SHA384 |
- TLS_ALGO_CIPHER_AES256_CBC);
-
- return TLS_Ciphersuite_Algos(0);
- }
-
-namespace {
-
-std::pair<std::string, size_t> cipher_code_to_name(TLS_Ciphersuite_Algos algo)
- {
- if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_RC4_128)
- return std::make_pair("ARC4", 16);
-
- if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_3DES_CBC)
- return std::make_pair("3DES", 24);
-
- if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_AES128_CBC)
- return std::make_pair("AES-128", 16);
-
- if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_AES256_CBC)
- return std::make_pair("AES-256", 32);
-
- if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_SEED_CBC)
- return std::make_pair("SEED", 16);
-
- throw TLS_Exception(INTERNAL_ERROR,
- "CipherSuite: Unknown cipher type " + to_string(algo));
- }
-
-std::string mac_code_to_name(TLS_Ciphersuite_Algos algo)
- {
- if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_MD5)
- return "MD5";
-
- if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA1)
- return "SHA-1";
-
- if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA256)
- return "SHA-256";
-
- if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA384)
- return "SHA-384";
-
- throw TLS_Exception(INTERNAL_ERROR,
- "CipherSuite: Unknown MAC type " + to_string(algo));
- }
-
-}
-
-/**
-* CipherSuite Constructor
-*/
-CipherSuite::CipherSuite(u16bit suite_code)
- {
- if(suite_code == 0)
- return;
-
- TLS_Ciphersuite_Algos algos = lookup_ciphersuite(suite_code);
-
- if(algos == 0)
- throw Invalid_Argument("Unknown ciphersuite: " + to_string(suite_code));
-
- sig_algo = TLS_Ciphersuite_Algos(algos & TLS_ALGO_SIGNER_MASK);
-
- kex_algo = TLS_Ciphersuite_Algos(algos & TLS_ALGO_KEYEXCH_MASK);
-
- std::pair<std::string, size_t> cipher_info = cipher_code_to_name(algos);
-
- cipher = cipher_info.first;
- cipher_key_length = cipher_info.second;
-
- mac = mac_code_to_name(algos);
- }
-
-}
diff --git a/src/ssl/tls_suites.h b/src/ssl/tls_suites.h
deleted file mode 100644
index 8d6db0e8b..000000000
--- a/src/ssl/tls_suites.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-* Cipher Suites
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CIPHERSUITES_H__
-#define BOTAN_TLS_CIPHERSUITES_H__
-
-#include <botan/types.h>
-#include <botan/tls_magic.h>
-#include <string>
-
-namespace Botan {
-
-/**
-* Ciphersuite Information
-*/
-class BOTAN_DLL CipherSuite
- {
- public:
- static TLS_Ciphersuite_Algos lookup_ciphersuite(u16bit suite);
-
- std::string cipher_algo() const { return cipher; }
- std::string mac_algo() const { return mac; }
-
- size_t cipher_keylen() const { return cipher_key_length; }
-
- TLS_Ciphersuite_Algos kex_type() const { return kex_algo; }
- TLS_Ciphersuite_Algos sig_type() const { return sig_algo; }
-
- CipherSuite(u16bit = 0);
- private:
- TLS_Ciphersuite_Algos kex_algo, sig_algo;
- std::string cipher, mac;
- size_t cipher_key_length;
- };
-
-}
-
-#endif
diff --git a/src/stream/arc4/arc4.cpp b/src/stream/arc4/arc4.cpp
index 6eea7bb45..13eb6ff9e 100644
--- a/src/stream/arc4/arc4.cpp
+++ b/src/stream/arc4/arc4.cpp
@@ -61,7 +61,10 @@ void ARC4::generate()
*/
void ARC4::key_schedule(const byte key[], size_t length)
{
- clear();
+ state.resize(256);
+ buffer.resize(DEFAULT_BUFFERSIZE);
+
+ position = X = Y = 0;
for(size_t i = 0; i != 256; ++i)
state[i] = static_cast<byte>(i);
@@ -85,7 +88,7 @@ std::string ARC4::name() const
{
if(SKIP == 0) return "ARC4";
if(SKIP == 256) return "MARK-4";
- else return "RC4_skip(" + to_string(SKIP) + ")";
+ else return "RC4_skip(" + std::to_string(SKIP) + ")";
}
/*
@@ -93,19 +96,14 @@ std::string ARC4::name() const
*/
void ARC4::clear()
{
- zeroise(state);
- zeroise(buffer);
+ state.clear();
+ buffer.clear();
position = X = Y = 0;
}
/*
* ARC4 Constructor
*/
-ARC4::ARC4(size_t s) : SKIP(s),
- state(256),
- buffer(DEFAULT_BUFFERSIZE)
- {
- clear();
- }
+ARC4::ARC4(size_t s) : SKIP(s) {}
}
diff --git a/src/stream/arc4/arc4.h b/src/stream/arc4/arc4.h
index e3df97f83..8f8de87b6 100644
--- a/src/stream/arc4/arc4.h
+++ b/src/stream/arc4/arc4.h
@@ -44,9 +44,9 @@ class BOTAN_DLL ARC4 : public StreamCipher
const size_t SKIP;
byte X, Y;
- SecureVector<byte> state;
+ secure_vector<byte> state;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
size_t position;
};
diff --git a/src/stream/ctr/ctr.cpp b/src/stream/ctr/ctr.cpp
index 3a370eca3..87ec86c65 100644
--- a/src/stream/ctr/ctr.cpp
+++ b/src/stream/ctr/ctr.cpp
@@ -49,7 +49,7 @@ void CTR_BE::key_schedule(const byte key[], size_t key_len)
permutation->set_key(key, key_len);
// Set a default all-zeros IV
- set_iv(0, 0);
+ set_iv(nullptr, 0);
}
/*
@@ -89,14 +89,14 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len)
zeroise(counter);
- counter.copy(0, iv, iv_len);
+ buffer_insert(counter, 0, iv, iv_len);
/*
* Set counter blocks to IV, IV + 1, ... IV + 255
*/
for(size_t i = 1; i != 256; ++i)
{
- counter.copy(i*bs, &counter[(i-1)*bs], bs);
+ buffer_insert(counter, i*bs, &counter[(i-1)*bs], bs);
for(size_t j = 0; j != bs; ++j)
if(++counter[i*bs + (bs - 1 - j)])
diff --git a/src/stream/ctr/ctr.h b/src/stream/ctr/ctr.h
index 64b43b0f5..9f391da7e 100644
--- a/src/stream/ctr/ctr.h
+++ b/src/stream/ctr/ctr.h
@@ -48,7 +48,7 @@ class BOTAN_DLL CTR_BE : public StreamCipher
void increment_counter();
BlockCipher* permutation;
- SecureVector<byte> counter, buffer;
+ secure_vector<byte> counter, buffer;
size_t position;
};
diff --git a/src/stream/ofb/ofb.cpp b/src/stream/ofb/ofb.cpp
index 382a2b4dd..1137a58af 100644
--- a/src/stream/ofb/ofb.cpp
+++ b/src/stream/ofb/ofb.cpp
@@ -46,7 +46,7 @@ void OFB::key_schedule(const byte key[], size_t key_len)
permutation->set_key(key, key_len);
// Set a default all-zeros IV
- set_iv(0, 0);
+ set_iv(nullptr, 0);
}
/*
@@ -84,7 +84,7 @@ void OFB::set_iv(const byte iv[], size_t iv_len)
throw Invalid_IV_Length(name(), iv_len);
zeroise(buffer);
- buffer.copy(0, iv, iv_len);
+ buffer_insert(buffer, 0, iv, iv_len);
permutation->encrypt(buffer);
position = 0;
diff --git a/src/stream/ofb/ofb.h b/src/stream/ofb/ofb.h
index c4d8b2601..9d4fd882f 100644
--- a/src/stream/ofb/ofb.h
+++ b/src/stream/ofb/ofb.h
@@ -47,7 +47,7 @@ class BOTAN_DLL OFB : public StreamCipher
void key_schedule(const byte key[], size_t key_len);
BlockCipher* permutation;
- SecureVector<byte> buffer;
+ secure_vector<byte> buffer;
size_t position;
};
diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp
index 7d062befe..a7d1b2622 100644
--- a/src/stream/salsa20/salsa20.cpp
+++ b/src/stream/salsa20/salsa20.cpp
@@ -134,7 +134,8 @@ void Salsa20::key_schedule(const byte key[], size_t length)
static const u32bit SIGMA[] =
{ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
- clear();
+ state.resize(16);
+ buffer.resize(64);
if(length == 16)
{
@@ -167,6 +168,8 @@ void Salsa20::key_schedule(const byte key[], size_t length)
state[15] = SIGMA[3];
}
+ position = 0;
+
const byte ZERO[8] = { 0 };
set_iv(ZERO, sizeof(ZERO));
}
@@ -193,7 +196,7 @@ void Salsa20::set_iv(const byte iv[], size_t length)
state[8] = load_le<u32bit>(iv, 2);
state[9] = load_le<u32bit>(iv, 3);
- SecureVector<u32bit> hsalsa(8);
+ secure_vector<u32bit> hsalsa(8);
hsalsa20(&hsalsa[0], &state[0]);
state[ 1] = hsalsa[0];
@@ -232,8 +235,8 @@ std::string Salsa20::name() const
*/
void Salsa20::clear()
{
- zeroise(state);
- zeroise(buffer);
+ state.clear();
+ buffer.clear();
position = 0;
}
diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h
index d9645015f..b68bb979e 100644
--- a/src/stream/salsa20/salsa20.h
+++ b/src/stream/salsa20/salsa20.h
@@ -33,13 +33,11 @@ class BOTAN_DLL Salsa20 : public StreamCipher
void clear();
std::string name() const;
StreamCipher* clone() const { return new Salsa20; }
-
- Salsa20() : state(16), buffer(64), position(0) {}
private:
void key_schedule(const byte key[], size_t key_len);
- SecureVector<u32bit> state;
- SecureVector<byte> buffer;
+ secure_vector<u32bit> state;
+ secure_vector<byte> buffer;
size_t position;
};
diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp
index 697c660ed..bdc53cff1 100644
--- a/src/stream/turing/turing.cpp
+++ b/src/stream/turing/turing.cpp
@@ -17,7 +17,7 @@ namespace {
/*
* Perform an N-way PHT
*/
-inline void PHT(MemoryRegion<u32bit>& B)
+inline void PHT(secure_vector<u32bit>& B)
{
u32bit sum = 0;
for(size_t i = 0; i < B.size() - 1; ++i)
@@ -247,6 +247,13 @@ void Turing::key_schedule(const byte key[], size_t length)
PHT(K);
+ R.resize(17);
+ S0.resize(256);
+ S1.resize(256);
+ S2.resize(256);
+ S3.resize(256);
+ buffer.resize(17*20);
+
for(u32bit i = 0; i != 256; ++i)
{
u32bit W0 = 0, C0 = i;
@@ -273,7 +280,7 @@ void Turing::key_schedule(const byte key[], size_t length)
S3[i] = (W3 & 0xFFFFFF00) | C3;
}
- set_iv(0, 0);
+ set_iv(nullptr, 0);
}
/*
@@ -284,7 +291,7 @@ void Turing::set_iv(const byte iv[], size_t length)
if(!valid_iv_length(length))
throw Invalid_IV_Length(name(), length);
- SecureVector<u32bit> IV(length / 4);
+ secure_vector<u32bit> IV(length / 4);
for(size_t i = 0; i != length; ++i)
IV[i/4] = (IV[i/4] << 8) + iv[i];
@@ -313,12 +320,13 @@ void Turing::set_iv(const byte iv[], size_t length)
*/
void Turing::clear()
{
- zeroise(S0);
- zeroise(S1);
- zeroise(S2);
- zeroise(S3);
-
- zeroise(buffer);
+ S0.clear();
+ S1.clear();
+ S2.clear();
+ S3.clear();
+ R.clear();
+ K.clear();
+ buffer.clear();
position = 0;
}
diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h
index aff314080..f2453127a 100644
--- a/src/stream/turing/turing.h
+++ b/src/stream/turing/turing.h
@@ -33,9 +33,6 @@ class BOTAN_DLL Turing : public StreamCipher
std::string name() const { return "Turing"; }
StreamCipher* clone() const { return new Turing; }
- Turing() : S0(256), S1(256), S2(256), S3(256),
- R(17), buffer(340), position(0) {}
-
private:
void key_schedule(const byte[], size_t);
void generate();
@@ -45,10 +42,9 @@ class BOTAN_DLL Turing : public StreamCipher
static const u32bit Q_BOX[256];
static const byte SBOX[256];
- SecureVector<u32bit> S0, S1, S2, S3;
- SecureVector<u32bit> R;
- SecureVector<u32bit> K;
- SecureVector<byte> buffer;
+ secure_vector<u32bit> S0, S1, S2, S3;
+ secure_vector<u32bit> R, K;
+ secure_vector<byte> buffer;
size_t position;
};
diff --git a/src/stream/wid_wake/wid_wake.cpp b/src/stream/wid_wake/wid_wake.cpp
index 51159064d..e4ab6477f 100644
--- a/src/stream/wid_wake/wid_wake.cpp
+++ b/src/stream/wid_wake/wid_wake.cpp
@@ -74,6 +74,10 @@ void WiderWake_41_BE::generate(size_t length)
*/
void WiderWake_41_BE::key_schedule(const byte key[], size_t)
{
+ t_key.resize(4);
+ state.resize(5);
+ buffer.resize(DEFAULT_BUFFERSIZE);
+
for(size_t i = 0; i != 4; ++i)
t_key[i] = load_be<u32bit>(key, i);
@@ -81,6 +85,7 @@ void WiderWake_41_BE::key_schedule(const byte key[], size_t)
0x726A8F3B, 0xE69A3B5C, 0xD3C71FE5, 0xAB3C73D2,
0x4D3A8EB3, 0x0396D6E8, 0x3D4C2F7A, 0x9EE27CF3 };
+ T.resize(256);
for(size_t i = 0; i != 4; ++i)
T[i] = t_key[i];
@@ -143,10 +148,10 @@ void WiderWake_41_BE::set_iv(const byte iv[], size_t length)
void WiderWake_41_BE::clear()
{
position = 0;
- zeroise(t_key);
- zeroise(state);
- zeroise(T);
- zeroise(buffer);
+ t_key.clear();
+ state.clear();
+ T.clear();
+ buffer.clear();
}
}
diff --git a/src/stream/wid_wake/wid_wake.h b/src/stream/wid_wake/wid_wake.h
index 05842a574..501345011 100644
--- a/src/stream/wid_wake/wid_wake.h
+++ b/src/stream/wid_wake/wid_wake.h
@@ -36,19 +36,15 @@ class BOTAN_DLL WiderWake_41_BE : public StreamCipher
std::string name() const { return "WiderWake4+1-BE"; }
StreamCipher* clone() const { return new WiderWake_41_BE; }
- WiderWake_41_BE() : T(256), state(5), t_key(4),
- buffer(DEFAULT_BUFFERSIZE), position(0)
- {}
-
private:
void key_schedule(const byte[], size_t);
void generate(size_t);
- SecureVector<u32bit> T;
- SecureVector<u32bit> state;
- SecureVector<u32bit> t_key;
- SecureVector<byte> buffer;
+ secure_vector<u32bit> T;
+ secure_vector<u32bit> state;
+ secure_vector<u32bit> t_key;
+ secure_vector<byte> buffer;
size_t position;
};
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp
new file mode 100644
index 000000000..e63dc91ba
--- /dev/null
+++ b/src/tls/c_hello.cpp
@@ -0,0 +1,394 @@
+/*
+* TLS Hello Request and Client Hello Messages
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/stl_util.h>
+#include <chrono>
+
+namespace Botan {
+
+namespace TLS {
+
+enum {
+ TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
+};
+
+std::vector<byte> make_hello_random(RandomNumberGenerator& rng)
+ {
+ std::vector<byte> buf(32);
+
+ const u32bit time32 = static_cast<u32bit>(
+ std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
+
+ store_be(time32, &buf[0]);
+ rng.randomize(&buf[4], buf.size() - 4);
+ return buf;
+ }
+
+/*
+* Create a new Hello Request message
+*/
+Hello_Request::Hello_Request(Record_Writer& writer)
+ {
+ writer.send(*this);
+ }
+
+/*
+* Deserialize a Hello Request message
+*/
+Hello_Request::Hello_Request(const std::vector<byte>& buf)
+ {
+ if(buf.size())
+ throw Decoding_Error("Bad Hello_Request, has non-zero size");
+ }
+
+/*
+* Serialize a Hello Request message
+*/
+std::vector<byte> Hello_Request::serialize() const
+ {
+ return std::vector<byte>();
+ }
+
+/*
+* Create a new Client Hello message
+*/
+Client_Hello::Client_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<byte>& reneg_info,
+ bool next_protocol,
+ const std::string& hostname,
+ const std::string& srp_identifier) :
+ m_version(policy.pref_version()),
+ m_random(make_hello_random(rng)),
+ m_suites(ciphersuite_list(policy, (srp_identifier != ""))),
+ m_comp_methods(policy.compression()),
+ m_hostname(hostname),
+ m_srp_identifier(srp_identifier),
+ m_next_protocol(next_protocol),
+ m_fragment_size(0),
+ m_secure_renegotiation(true),
+ m_renegotiation_info(reneg_info),
+ m_supported_curves(policy.allowed_ecc_curves()),
+ m_supports_session_ticket(true),
+ m_supports_heartbeats(true),
+ m_peer_can_send_heartbeats(true)
+ {
+ std::vector<std::string> hashes = policy.allowed_hashes();
+ std::vector<std::string> sigs = policy.allowed_signature_methods();
+
+ for(size_t i = 0; i != hashes.size(); ++i)
+ for(size_t j = 0; j != sigs.size(); ++j)
+ m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
+
+ hash.update(writer.send(*this));
+ }
+
+/*
+* Create a new Client Hello message (session resumption case)
+*/
+Client_Hello::Client_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<byte>& reneg_info,
+ const Session& session,
+ bool next_protocol) :
+ m_version(session.version()),
+ m_session_id(session.session_id()),
+ m_random(make_hello_random(rng)),
+ m_suites(ciphersuite_list(policy, (session.srp_identifier() != ""))),
+ m_comp_methods(policy.compression()),
+ m_hostname(session.sni_hostname()),
+ m_srp_identifier(session.srp_identifier()),
+ m_next_protocol(next_protocol),
+ m_fragment_size(session.fragment_size()),
+ m_secure_renegotiation(session.secure_renegotiation()),
+ m_renegotiation_info(reneg_info),
+ m_supported_curves(policy.allowed_ecc_curves()),
+ m_supports_session_ticket(true),
+ m_session_ticket(session.session_ticket()),
+ m_supports_heartbeats(true),
+ m_peer_can_send_heartbeats(true)
+ {
+ if(!value_exists(m_suites, session.ciphersuite_code()))
+ m_suites.push_back(session.ciphersuite_code());
+
+ if(!value_exists(m_comp_methods, session.compression_method()))
+ m_comp_methods.push_back(session.compression_method());
+
+ std::vector<std::string> hashes = policy.allowed_hashes();
+ std::vector<std::string> sigs = policy.allowed_signature_methods();
+
+ for(size_t i = 0; i != hashes.size(); ++i)
+ for(size_t j = 0; j != sigs.size(); ++j)
+ m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
+
+ hash.update(writer.send(*this));
+ }
+
+/*
+* Read a counterparty client hello
+*/
+Client_Hello::Client_Hello(const std::vector<byte>& buf, Handshake_Type type)
+ {
+ m_next_protocol = false;
+ m_secure_renegotiation = false;
+ m_supports_session_ticket = false;
+ m_supports_heartbeats = false;
+ m_peer_can_send_heartbeats = false;
+ m_fragment_size = 0;
+
+ if(type == CLIENT_HELLO)
+ deserialize(buf);
+ else
+ deserialize_sslv2(buf);
+ }
+
+/*
+* Serialize a Client Hello message
+*/
+std::vector<byte> Client_Hello::serialize() const
+ {
+ std::vector<byte> buf;
+
+ buf.push_back(m_version.major_version());
+ buf.push_back(m_version.minor_version());
+ buf += m_random;
+
+ append_tls_length_value(buf, m_session_id, 1);
+ append_tls_length_value(buf, m_suites, 2);
+ append_tls_length_value(buf, m_comp_methods, 1);
+
+ /*
+ * May not want to send extensions at all in some cases.
+ * If so, should include SCSV value (if reneg info is empty, if
+ * not we are renegotiating with a modern server and should only
+ * send that extension.
+ */
+
+ Extensions extensions;
+
+ if(m_secure_renegotiation)
+ extensions.add(new Renegotation_Extension(m_renegotiation_info));
+
+ extensions.add(new Session_Ticket(m_session_ticket));
+
+ extensions.add(new Server_Name_Indicator(m_hostname));
+ extensions.add(new SRP_Identifier(m_srp_identifier));
+
+ extensions.add(new Supported_Elliptic_Curves(m_supported_curves));
+
+ if(m_version >= Protocol_Version::TLS_V12)
+ extensions.add(new Signature_Algorithms(m_supported_algos));
+
+ extensions.add(new Heartbeat_Support_Indicator(true));
+
+ if(m_renegotiation_info.empty() && m_next_protocol)
+ extensions.add(new Next_Protocol_Notification());
+
+ buf += extensions.serialize();
+
+ return buf;
+ }
+
+void Client_Hello::deserialize_sslv2(const std::vector<byte>& buf)
+ {
+ if(buf.size() < 12 || buf[0] != 1)
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+
+ const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]);
+ const size_t m_session_id_len = make_u16bit(buf[5], buf[6]);
+ const size_t challenge_len = make_u16bit(buf[7], buf[8]);
+
+ const size_t expected_size =
+ (9 + m_session_id_len + cipher_spec_len + challenge_len);
+
+ if(buf.size() != expected_size)
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+
+ if(m_session_id_len != 0 || cipher_spec_len % 3 != 0 ||
+ (challenge_len < 16 || challenge_len > 32))
+ {
+ throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
+ }
+
+ for(size_t i = 9; i != 9 + cipher_spec_len; i += 3)
+ {
+ if(buf[i] != 0) // a SSLv2 cipherspec; ignore it
+ continue;
+
+ m_suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
+ }
+
+ m_version = Protocol_Version(buf[1], buf[2]);
+
+ m_random.resize(challenge_len);
+ copy_mem(&m_random[0], &buf[9+cipher_spec_len+m_session_id_len], challenge_len);
+
+ m_secure_renegotiation =
+ value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV));
+ }
+
+/*
+* Deserialize a Client Hello message
+*/
+void Client_Hello::deserialize(const std::vector<byte>& buf)
+ {
+ if(buf.size() == 0)
+ throw Decoding_Error("Client_Hello: Packet corrupted");
+
+ if(buf.size() < 41)
+ throw Decoding_Error("Client_Hello: Packet corrupted");
+
+ TLS_Data_Reader reader(buf);
+
+ const byte major_version = reader.get_byte();
+ const byte minor_version = reader.get_byte();
+
+ m_version = Protocol_Version(major_version, minor_version);
+
+ m_random = reader.get_fixed<byte>(32);
+
+ m_session_id = reader.get_range<byte>(1, 0, 32);
+
+ m_suites = reader.get_range_vector<u16bit>(2, 1, 32767);
+
+ m_comp_methods = reader.get_range_vector<byte>(1, 1, 255);
+
+ Extensions extensions(reader);
+
+ if(Server_Name_Indicator* sni = extensions.get<Server_Name_Indicator>())
+ {
+ m_hostname = sni->host_name();
+ }
+
+ if(SRP_Identifier* srp = extensions.get<SRP_Identifier>())
+ {
+ m_srp_identifier = srp->identifier();
+ }
+
+ if(Next_Protocol_Notification* npn = extensions.get<Next_Protocol_Notification>())
+ {
+ if(!npn->protocols().empty())
+ throw Decoding_Error("Client sent non-empty NPN extension");
+
+ m_next_protocol = true;
+ }
+
+ if(Maximum_Fragment_Length* frag = extensions.get<Maximum_Fragment_Length>())
+ {
+ m_fragment_size = frag->fragment_size();
+ }
+
+ if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>())
+ {
+ // checked by Client / Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+
+ if(Supported_Elliptic_Curves* ecc = extensions.get<Supported_Elliptic_Curves>())
+ m_supported_curves = ecc->curves();
+
+ if(Signature_Algorithms* sigs = extensions.get<Signature_Algorithms>())
+ {
+ m_supported_algos = sigs->supported_signature_algorthms();
+ }
+ else
+ {
+ if(m_version >= Protocol_Version::TLS_V12)
+ {
+ /*
+ The rule for when a TLS 1.2 client not sending the extension
+ is strange; in theory, the server is supposed to act as if
+ the client had sent only SHA-1 using whatever signature
+ algorithm we end up negotiating. Right here, we don't know
+ what we'll end up negotiating (depends on policy), but we do
+ know that we'll only negotiate something the client sent, so
+ we can safely say it supports everything here and know that
+ we'll filter it out later.
+ */
+ m_supported_algos.push_back(std::make_pair("SHA-1", "RSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
+ }
+ else
+ {
+ // For versions before TLS 1.2, insert fake values for the old defaults
+
+ m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
+ }
+ }
+
+ if(Maximum_Fragment_Length* frag = extensions.get<Maximum_Fragment_Length>())
+ {
+ m_fragment_size = frag->fragment_size();
+ }
+
+ if(Session_Ticket* ticket = extensions.get<Session_Ticket>())
+ {
+ m_supports_session_ticket = true;
+ m_session_ticket = ticket->contents();
+ }
+
+ if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>())
+ {
+ m_supports_heartbeats = true;
+ m_peer_can_send_heartbeats = hb->peer_allowed_to_send();
+ }
+
+ if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>())
+ {
+ // checked by TLS_Client / TLS_Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+
+ if(value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
+ {
+ /*
+ * Clients are allowed to send both the extension and the SCSV
+ * though it is not recommended. If it did, require that the
+ * extension value be empty.
+ */
+ if(m_secure_renegotiation)
+ {
+ if(!m_renegotiation_info.empty())
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client send SCSV and non-empty extension");
+ }
+ }
+
+ m_secure_renegotiation = true;
+ m_renegotiation_info.clear();
+ }
+ }
+
+/*
+* Check if we offered this ciphersuite
+*/
+bool Client_Hello::offered_suite(u16bit ciphersuite) const
+ {
+ for(size_t i = 0; i != m_suites.size(); ++i)
+ if(m_suites[i] == ciphersuite)
+ return true;
+ return false;
+ }
+
+}
+
+}
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp
new file mode 100644
index 000000000..5ff9ec1ce
--- /dev/null
+++ b/src/tls/c_kex.cpp
@@ -0,0 +1,393 @@
+/*
+* Client Key Exchange Message
+* (C) 2004-2010 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/assert.h>
+#include <botan/credentials_manager.h>
+#include <botan/pubkey.h>
+#include <botan/dh.h>
+#include <botan/ecdh.h>
+#include <botan/rsa.h>
+#include <botan/srp6.h>
+#include <botan/rng.h>
+#include <botan/loadstor.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+secure_vector<byte> strip_leading_zeros(const secure_vector<byte>& input)
+ {
+ size_t leading_zeros = 0;
+
+ for(size_t i = 0; i != input.size(); ++i)
+ {
+ if(input[i] != 0)
+ break;
+ ++leading_zeros;
+ }
+
+ secure_vector<byte> output(&input[leading_zeros],
+ &input[input.size()-1]);
+ return output;
+ }
+
+}
+
+/*
+* Create a new Client Key Exchange message
+*/
+Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer,
+ Handshake_State* state,
+ Credentials_Manager& creds,
+ const std::vector<X509_Certificate>& peer_certs,
+ const std::string& hostname,
+ RandomNumberGenerator& rng)
+ {
+ const std::string kex_algo = state->suite.kex_algo();
+
+ if(kex_algo == "PSK")
+ {
+ std::string identity_hint = "";
+
+ if(state->server_kex)
+ {
+ TLS_Data_Reader reader(state->server_kex->params());
+ identity_hint = reader.get_string(2, 0, 65535);
+ }
+
+ const std::string hostname = state->client_hello->sni_hostname();
+
+ const std::string psk_identity = creds.psk_identity("tls-client",
+ hostname,
+ identity_hint);
+
+ append_tls_length_value(key_material, psk_identity, 2);
+
+ SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);
+
+ std::vector<byte> zeros(psk.length());
+
+ append_tls_length_value(pre_master, zeros, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+ else if(state->server_kex)
+ {
+ TLS_Data_Reader reader(state->server_kex->params());
+
+ SymmetricKey psk;
+
+ if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
+ {
+ std::string identity_hint = reader.get_string(2, 0, 65535);
+
+ const std::string hostname = state->client_hello->sni_hostname();
+
+ const std::string psk_identity = creds.psk_identity("tls-client",
+ hostname,
+ identity_hint);
+
+ append_tls_length_value(key_material, psk_identity, 2);
+
+ psk = creds.psk("tls-client", hostname, psk_identity);
+ }
+
+ if(kex_algo == "DH" || kex_algo == "DHE_PSK")
+ {
+ BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+
+ if(reader.remaining_bytes())
+ throw Decoding_Error("Bad params size for DH key exchange");
+
+ DL_Group group(p, g);
+
+ if(!group.verify_group(rng, true))
+ throw Internal_Error("DH group failed validation, possible attack");
+
+ DH_PublicKey counterparty_key(group, Y);
+
+ // FIXME Check that public key is residue?
+
+ DH_PrivateKey priv_key(rng, group);
+
+ PK_Key_Agreement ka(priv_key, "Raw");
+
+ secure_vector<byte> dh_secret = strip_leading_zeros(
+ ka.derive_key(0, counterparty_key.public_value()).bits_of());
+
+ if(kex_algo == "DH")
+ pre_master = dh_secret;
+ else
+ {
+ append_tls_length_value(pre_master, dh_secret, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+
+ append_tls_length_value(key_material, priv_key.public_value(), 2);
+ }
+ else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
+ {
+ const byte curve_type = reader.get_byte();
+
+ if(curve_type != 3)
+ throw Decoding_Error("Server sent non-named ECC curve");
+
+ const u16bit curve_id = reader.get_u16bit();
+
+ const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);
+
+ if(name == "")
+ throw Decoding_Error("Server sent unknown named curve " + std::to_string(curve_id));
+
+ EC_Group group(name);
+
+ std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);
+
+ ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));
+
+ ECDH_PrivateKey priv_key(rng, group);
+
+ PK_Key_Agreement ka(priv_key, "Raw");
+
+ secure_vector<byte> ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of();
+
+ if(kex_algo == "ECDH")
+ pre_master = ecdh_secret;
+ else
+ {
+ append_tls_length_value(pre_master, ecdh_secret, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+
+ append_tls_length_value(key_material, priv_key.public_value(), 1);
+ }
+ else if(kex_algo == "SRP_SHA")
+ {
+ const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ std::vector<byte> salt = reader.get_range<byte>(1, 1, 255);
+ const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+
+ const std::string srp_group = srp6_group_identifier(N, g);
+
+ const std::string srp_identifier =
+ creds.srp_identifier("tls-client", hostname);
+
+ const std::string srp_password =
+ creds.srp_password("tls-client", hostname, srp_identifier);
+
+ std::pair<BigInt, SymmetricKey> srp_vals =
+ srp6_client_agree(srp_identifier,
+ srp_password,
+ srp_group,
+ "SHA-1",
+ salt,
+ B,
+ rng);
+
+ append_tls_length_value(key_material, BigInt::encode(srp_vals.first), 2);
+ pre_master = srp_vals.second.bits_of();
+ }
+ else
+ {
+ throw Internal_Error("Client_Key_Exchange: Unknown kex " +
+ kex_algo);
+ }
+ }
+ else
+ {
+ // No server key exchange msg better mean RSA kex + RSA key in cert
+
+ if(kex_algo != "RSA")
+ throw Unexpected_Message("No server kex but negotiated kex " + kex_algo);
+
+ if(peer_certs.empty())
+ throw Internal_Error("No certificate and no server key exchange");
+
+ std::unique_ptr<Public_Key> pub_key(peer_certs[0].subject_public_key());
+
+ if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get()))
+ {
+ const Protocol_Version pref_version = state->client_hello->version();
+
+ pre_master = rng.random_vec(48);
+ pre_master[0] = pref_version.major_version();
+ pre_master[1] = pref_version.minor_version();
+
+ PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");
+
+ std::vector<byte> encrypted_key = encryptor.encrypt(pre_master, rng);
+
+ if(state->version() == Protocol_Version::SSL_V3)
+ key_material = encrypted_key; // no length field
+ else
+ append_tls_length_value(key_material, encrypted_key, 2);
+ }
+ else
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Expected a RSA key in server cert but got " +
+ pub_key->algo_name());
+ }
+
+ state->hash.update(writer.send(*this));
+ }
+
+/*
+* Read a Client Key Exchange message
+*/
+Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents,
+ const Handshake_State* state,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng)
+ {
+ const std::string kex_algo = state->suite.kex_algo();
+
+ if(kex_algo == "RSA")
+ {
+ BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(),
+ "No server certificate to use for RSA");
+
+ const Private_Key* private_key = state->server_rsa_kex_key;
+
+ if(!private_key)
+ throw Internal_Error("Expected RSA kex but no server kex key set");
+
+ if(!dynamic_cast<const RSA_PrivateKey*>(private_key))
+ throw Internal_Error("Expected RSA key but got " + private_key->algo_name());
+
+ PK_Decryptor_EME decryptor(*private_key, "PKCS1v15");
+
+ Protocol_Version client_version = state->client_hello->version();
+
+ try
+ {
+ if(state->version() == Protocol_Version::SSL_V3)
+ {
+ pre_master = decryptor.decrypt(contents);
+ }
+ else
+ {
+ TLS_Data_Reader reader(contents);
+ pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));
+ }
+
+ if(pre_master.size() != 48 ||
+ client_version.major_version() != pre_master[0] ||
+ client_version.minor_version() != pre_master[1])
+ {
+ throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
+ }
+ }
+ catch(...)
+ {
+ // Randomize the hide timing channel
+ pre_master = rng.random_vec(48);
+ pre_master[0] = client_version.major_version();
+ pre_master[1] = client_version.minor_version();
+ }
+ }
+ else
+ {
+ TLS_Data_Reader reader(contents);
+
+ SymmetricKey psk;
+
+ if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
+ {
+ const std::string psk_identity = reader.get_string(2, 0, 65535);
+
+ psk = creds.psk("tls-server",
+ state->client_hello->sni_hostname(),
+ psk_identity);
+
+ if(psk.length() == 0)
+ {
+ if(policy.hide_unknown_users())
+ psk = SymmetricKey(rng, 16);
+ else
+ throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
+ "No PSK for identifier " + psk_identity);
+ }
+
+ }
+
+ if(kex_algo == "PSK")
+ {
+ std::vector<byte> zeros(psk.length());
+ append_tls_length_value(pre_master, zeros, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+ else if(kex_algo == "SRP_SHA")
+ {
+ SRP6_Server_Session& srp = state->server_kex->server_srp_params();
+
+ pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of();
+ }
+ else if(kex_algo == "DH" || kex_algo == "DHE_PSK" ||
+ kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
+ {
+ const Private_Key& private_key = state->server_kex->server_kex_key();
+
+ const PK_Key_Agreement_Key* ka_key =
+ dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
+
+ if(!ka_key)
+ throw Internal_Error("Expected key agreement key type but got " +
+ private_key.algo_name());
+
+ try
+ {
+ PK_Key_Agreement ka(*ka_key, "Raw");
+
+ std::vector<byte> client_pubkey;
+
+ if(ka_key->algo_name() == "DH")
+ client_pubkey = reader.get_range<byte>(2, 0, 65535);
+ else
+ client_pubkey = reader.get_range<byte>(1, 0, 255);
+
+ secure_vector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
+
+ if(ka_key->algo_name() == "DH")
+ shared_secret = strip_leading_zeros(shared_secret);
+
+ if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
+ {
+ append_tls_length_value(pre_master, shared_secret, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+ else
+ pre_master = shared_secret;
+ }
+ catch(std::exception &e)
+ {
+ /*
+ * Something failed in the DH computation. To avoid possible
+ * timing attacks, randomize the pre-master output and carry
+ * on, allowing the protocol to fail later in the finished
+ * checks.
+ */
+ pre_master = rng.random_vec(ka_key->public_value().size());
+ }
+ }
+ else
+ throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
+ }
+ }
+
+}
+
+}
diff --git a/src/tls/cert_req.cpp b/src/tls/cert_req.cpp
new file mode 100644
index 000000000..6ec5339bb
--- /dev/null
+++ b/src/tls/cert_req.cpp
@@ -0,0 +1,241 @@
+/*
+* Certificate Request Message
+* (C) 2004-2006,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+std::string cert_type_code_to_name(byte code)
+ {
+ switch(code)
+ {
+ case 1:
+ return "RSA";
+ case 2:
+ return "DSA";
+ case 64:
+ return "ECDSA";
+ default:
+ return ""; // DH or something else
+ }
+ }
+
+byte cert_type_name_to_code(const std::string& name)
+ {
+ if(name == "RSA")
+ return 1;
+ if(name == "DSA")
+ return 2;
+ if(name == "ECDSA")
+ return 64;
+
+ throw Invalid_Argument("Unknown cert type " + name);
+ }
+
+}
+
+/**
+* Create a new Certificate Request message
+*/
+Certificate_Req::Certificate_Req(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ const std::vector<X509_Certificate>& ca_certs,
+ Protocol_Version version)
+ {
+ for(size_t i = 0; i != ca_certs.size(); ++i)
+ names.push_back(ca_certs[i].subject_dn());
+
+ cert_key_types.push_back("RSA");
+ cert_key_types.push_back("DSA");
+ cert_key_types.push_back("ECDSA");
+
+ if(version >= Protocol_Version::TLS_V12)
+ {
+ std::vector<std::string> hashes = policy.allowed_hashes();
+ std::vector<std::string> sigs = policy.allowed_signature_methods();
+
+ for(size_t i = 0; i != hashes.size(); ++i)
+ for(size_t j = 0; j != sigs.size(); ++j)
+ m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
+ }
+
+ hash.update(writer.send(*this));
+ }
+
+/**
+* Deserialize a Certificate Request message
+*/
+Certificate_Req::Certificate_Req(const std::vector<byte>& buf,
+ Protocol_Version version)
+ {
+ if(buf.size() < 4)
+ throw Decoding_Error("Certificate_Req: Bad certificate request");
+
+ TLS_Data_Reader reader(buf);
+
+ std::vector<byte> cert_type_codes = reader.get_range_vector<byte>(1, 1, 255);
+
+ for(size_t i = 0; i != cert_type_codes.size(); ++i)
+ {
+ const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]);
+
+ if(cert_type_name == "") // something we don't know
+ continue;
+
+ cert_key_types.push_back(cert_type_name);
+ }
+
+ if(version >= Protocol_Version::TLS_V12)
+ {
+ std::vector<byte> sig_hash_algs = reader.get_range_vector<byte>(2, 2, 65534);
+
+ if(sig_hash_algs.size() % 2 != 0)
+ throw Decoding_Error("Bad length for signature IDs in certificate request");
+
+ for(size_t i = 0; i != sig_hash_algs.size(); i += 2)
+ {
+ std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]);
+ std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]);
+ m_supported_algos.push_back(std::make_pair(hash, sig));
+ }
+ }
+ else
+ {
+ // The hardcoded settings from previous protocol versions
+ m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
+ }
+
+ const u16bit purported_size = reader.get_u16bit();
+
+ if(reader.remaining_bytes() != purported_size)
+ throw Decoding_Error("Inconsistent length in certificate request");
+
+ while(reader.has_remaining())
+ {
+ std::vector<byte> name_bits = reader.get_range_vector<byte>(2, 0, 65535);
+
+ BER_Decoder decoder(&name_bits[0], name_bits.size());
+ X509_DN name;
+ decoder.decode(name);
+ names.push_back(name);
+ }
+ }
+
+/**
+* Serialize a Certificate Request message
+*/
+std::vector<byte> Certificate_Req::serialize() const
+ {
+ std::vector<byte> buf;
+
+ std::vector<byte> cert_types;
+
+ for(size_t i = 0; i != cert_key_types.size(); ++i)
+ cert_types.push_back(cert_type_name_to_code(cert_key_types[i]));
+
+ append_tls_length_value(buf, cert_types, 1);
+
+ if(!m_supported_algos.empty())
+ buf += Signature_Algorithms(m_supported_algos).serialize();
+
+ std::vector<byte> encoded_names;
+
+ for(size_t i = 0; i != names.size(); ++i)
+ {
+ DER_Encoder encoder;
+ encoder.encode(names[i]);
+
+ append_tls_length_value(encoded_names, encoder.get_contents(), 2);
+ }
+
+ append_tls_length_value(buf, encoded_names, 2);
+
+ return buf;
+ }
+
+/**
+* Create a new Certificate message
+*/
+Certificate::Certificate(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<X509_Certificate>& cert_list) :
+ m_certs(cert_list)
+ {
+ hash.update(writer.send(*this));
+ }
+
+/**
+* Deserialize a Certificate message
+*/
+Certificate::Certificate(const std::vector<byte>& buf)
+ {
+ if(buf.size() < 3)
+ throw Decoding_Error("Certificate: Message malformed");
+
+ const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]);
+
+ if(total_size != buf.size() - 3)
+ throw Decoding_Error("Certificate: Message malformed");
+
+ const byte* certs = &buf[3];
+
+ while(size_t remaining_bytes = &buf[buf.size()] - certs)
+ {
+ if(remaining_bytes < 3)
+ throw Decoding_Error("Certificate: Message malformed");
+
+ const size_t cert_size = make_u32bit(0, certs[0], certs[1], certs[2]);
+
+ if(remaining_bytes < (3 + cert_size))
+ throw Decoding_Error("Certificate: Message malformed");
+
+ DataSource_Memory cert_buf(&certs[3], cert_size);
+ m_certs.push_back(X509_Certificate(cert_buf));
+
+ certs += cert_size + 3;
+ }
+ }
+
+/**
+* Serialize a Certificate message
+*/
+std::vector<byte> Certificate::serialize() const
+ {
+ std::vector<byte> buf(3);
+
+ for(size_t i = 0; i != m_certs.size(); ++i)
+ {
+ std::vector<byte> raw_cert = m_certs[i].BER_encode();
+ const size_t cert_size = raw_cert.size();
+ for(size_t i = 0; i != 3; ++i)
+ buf.push_back(get_byte<u32bit>(i+1, cert_size));
+ buf += raw_cert;
+ }
+
+ const size_t buf_size = buf.size() - 3;
+ for(size_t i = 0; i != 3; ++i)
+ buf[i] = get_byte<u32bit>(i+1, buf_size);
+
+ return buf;
+ }
+
+}
+
+}
diff --git a/src/tls/cert_ver.cpp b/src/tls/cert_ver.cpp
new file mode 100644
index 000000000..e6d90b060
--- /dev/null
+++ b/src/tls/cert_ver.cpp
@@ -0,0 +1,117 @@
+/*
+* Certificate Verify Message
+* (C) 2004,2006,2011,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/assert.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+/*
+* Create a new Certificate Verify message
+*/
+Certificate_Verify::Certificate_Verify(Record_Writer& writer,
+ Handshake_State* state,
+ RandomNumberGenerator& rng,
+ const Private_Key* priv_key)
+ {
+ BOTAN_ASSERT_NONNULL(priv_key);
+
+ std::pair<std::string, Signature_Format> format =
+ state->choose_sig_format(priv_key, hash_algo, sig_algo, true);
+
+ PK_Signer signer(*priv_key, format.first, format.second);
+
+ if(state->version() == Protocol_Version::SSL_V3)
+ {
+ secure_vector<byte> md5_sha = state->hash.final_ssl3(
+ state->keys.master_secret());
+
+ if(priv_key->algo_name() == "DSA")
+ signature = signer.sign_message(&md5_sha[16], md5_sha.size()-16, rng);
+ else
+ signature = signer.sign_message(md5_sha, rng);
+ }
+ else
+ {
+ signature = signer.sign_message(state->hash.get_contents(), rng);
+ }
+
+ state->hash.update(writer.send(*this));
+ }
+
+/*
+* Deserialize a Certificate Verify message
+*/
+Certificate_Verify::Certificate_Verify(const std::vector<byte>& buf,
+ Protocol_Version version)
+ {
+ TLS_Data_Reader reader(buf);
+
+ if(version >= Protocol_Version::TLS_V12)
+ {
+ hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte());
+ sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte());
+ }
+
+ signature = reader.get_range<byte>(2, 0, 65535);
+ }
+
+/*
+* Serialize a Certificate Verify message
+*/
+std::vector<byte> Certificate_Verify::serialize() const
+ {
+ std::vector<byte> buf;
+
+ if(hash_algo != "" && sig_algo != "")
+ {
+ buf.push_back(Signature_Algorithms::hash_algo_code(hash_algo));
+ buf.push_back(Signature_Algorithms::sig_algo_code(sig_algo));
+ }
+
+ const u16bit sig_len = signature.size();
+ buf.push_back(get_byte(0, sig_len));
+ buf.push_back(get_byte(1, sig_len));
+ buf += signature;
+
+ return buf;
+ }
+
+/*
+* Verify a Certificate Verify message
+*/
+bool Certificate_Verify::verify(const X509_Certificate& cert,
+ Handshake_State* state)
+ {
+ std::unique_ptr<Public_Key> key(cert.subject_public_key());
+
+ std::pair<std::string, Signature_Format> format =
+ state->understand_sig_format(key.get(), hash_algo, sig_algo, true);
+
+ PK_Verifier verifier(*key, format.first, format.second);
+
+ if(state->version() == Protocol_Version::SSL_V3)
+ {
+ secure_vector<byte> md5_sha = state->hash.final_ssl3(
+ state->keys.master_secret());
+
+ return verifier.verify_message(&md5_sha[16], md5_sha.size()-16,
+ &signature[0], signature.size());
+ }
+
+ return verifier.verify_message(state->hash.get_contents(), signature);
+ }
+
+}
+
+}
diff --git a/src/tls/finished.cpp b/src/tls/finished.cpp
new file mode 100644
index 000000000..c8ae4a343
--- /dev/null
+++ b/src/tls/finished.cpp
@@ -0,0 +1,104 @@
+/*
+* Finished Message
+* (C) 2004-2006,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/tls_record.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+/*
+* Compute the verify_data
+*/
+std::vector<byte> finished_compute_verify(Handshake_State* state,
+ Connection_Side side)
+ {
+ if(state->version() == Protocol_Version::SSL_V3)
+ {
+ const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 };
+ const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 };
+
+ Handshake_Hash hash = state->hash; // don't modify state
+
+ std::vector<byte> ssl3_finished;
+
+ if(side == CLIENT)
+ hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL));
+ else
+ hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL));
+
+ return unlock(hash.final_ssl3(state->keys.master_secret()));
+ }
+ else
+ {
+ const byte TLS_CLIENT_LABEL[] = {
+ 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69,
+ 0x73, 0x68, 0x65, 0x64 };
+
+ const byte TLS_SERVER_LABEL[] = {
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69,
+ 0x73, 0x68, 0x65, 0x64 };
+
+ std::unique_ptr<KDF> prf(state->protocol_specific_prf());
+
+ std::vector<byte> input;
+ if(side == CLIENT)
+ input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL));
+ else
+ input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL));
+
+ input += state->hash.final(state->version(), state->suite.mac_algo());
+
+ return unlock(prf->derive_key(12, state->keys.master_secret(), input));
+ }
+ }
+
+}
+
+/*
+* Create a new Finished message
+*/
+Finished::Finished(Record_Writer& writer,
+ Handshake_State* state,
+ Connection_Side side)
+ {
+ verification_data = finished_compute_verify(state, side);
+ state->hash.update(writer.send(*this));
+ }
+
+/*
+* Serialize a Finished message
+*/
+std::vector<byte> Finished::serialize() const
+ {
+ return verification_data;
+ }
+
+/*
+* Deserialize a Finished message
+*/
+Finished::Finished(const std::vector<byte>& buf)
+ {
+ verification_data = buf;
+ }
+
+/*
+* Verify a Finished message
+*/
+bool Finished::verify(Handshake_State* state,
+ Connection_Side side)
+ {
+ return (verification_data == finished_compute_verify(state, side));
+ }
+
+}
+
+}
diff --git a/src/tls/hello_verify.cpp b/src/tls/hello_verify.cpp
new file mode 100644
index 000000000..c77076e4c
--- /dev/null
+++ b/src/tls/hello_verify.cpp
@@ -0,0 +1,61 @@
+/*
+* DTLS Hello Verify Request
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& buf)
+ {
+ if(buf.size() < 3)
+ throw Decoding_Error("Hello verify request too small");
+
+ if(buf[0] != 254 || (buf[1] != 255 && buf[1] != 253))
+ throw Decoding_Error("Unknown version from server in hello verify request");
+
+ m_cookie.resize(buf.size() - 2);
+ copy_mem(&m_cookie[0], &buf[2], buf.size() - 2);
+ }
+
+Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& client_hello_bits,
+ const std::string& client_identity,
+ const SymmetricKey& secret_key)
+ {
+ std::unique_ptr<MessageAuthenticationCode> hmac(get_mac("HMAC(SHA-256)"));
+ hmac->set_key(secret_key);
+
+ hmac->update_be(client_hello_bits.size());
+ hmac->update(client_hello_bits);
+ hmac->update_be(client_identity.size());
+ hmac->update(client_identity);
+
+ m_cookie = unlock(hmac->final());
+ }
+
+std::vector<byte> Hello_Verify_Request::serialize() const
+ {
+ /* DTLS 1.2 server implementations SHOULD use DTLS version 1.0
+ regardless of the version of TLS that is expected to be
+ negotiated (RFC 6347, section 4.2.1)
+ */
+
+ Protocol_Version format_version(Protocol_Version::TLS_V11);
+
+ std::vector<byte> bits;
+ bits.push_back(format_version.major_version());
+ bits.push_back(format_version.minor_version());
+ bits += m_cookie;
+ return bits;
+ }
+
+}
+
+}
diff --git a/src/tls/info.txt b/src/tls/info.txt
new file mode 100644
index 000000000..9c0051abd
--- /dev/null
+++ b/src/tls/info.txt
@@ -0,0 +1,95 @@
+define TLS
+
+load_on auto
+
+<comment>
+The TLS code is complex, new, and not yet reviewed, there may be
+serious bugs or security issues.
+</comment>
+
+<header:public>
+tls_alert.h
+tls_channel.h
+tls_ciphersuite.h
+tls_client.h
+tls_exceptn.h
+tls_magic.h
+tls_policy.h
+tls_record.h
+tls_server.h
+tls_session.h
+tls_session_manager.h
+tls_version.h
+</header:public>
+
+<header:internal>
+tls_extensions.h
+tls_handshake_hash.h
+tls_handshake_reader.h
+tls_handshake_state.h
+tls_heartbeats.h
+tls_messages.h
+tls_reader.h
+tls_session_key.h
+</header:internal>
+
+<source>
+c_hello.cpp
+c_kex.cpp
+cert_req.cpp
+cert_ver.cpp
+finished.cpp
+hello_verify.cpp
+next_protocol.cpp
+rec_read.cpp
+rec_wri.cpp
+s_hello.cpp
+s_kex.cpp
+session_ticket.cpp
+tls_alert.cpp
+tls_channel.cpp
+tls_ciphersuite.cpp
+tls_client.cpp
+tls_extensions.cpp
+tls_handshake_hash.cpp
+tls_handshake_reader.cpp
+tls_handshake_state.cpp
+tls_heartbeats.cpp
+tls_policy.cpp
+tls_server.cpp
+tls_session.cpp
+tls_session_key.cpp
+tls_session_manager.cpp
+tls_suite_info.cpp
+tls_version.cpp
+</source>
+
+<requires>
+aes
+arc4
+asn1
+camellia
+cbc
+credentials
+des
+dh
+dsa
+ecdh
+ecdsa
+eme_pkcs
+emsa3
+filters
+hmac
+kdf2
+md5
+prf_ssl3
+prf_tls
+rng
+rsa
+seed
+srp6
+sha1
+sha2_32
+ssl3mac
+x509
+</requires>
diff --git a/src/tls/next_protocol.cpp b/src/tls/next_protocol.cpp
new file mode 100644
index 000000000..adf9acbe9
--- /dev/null
+++ b/src/tls/next_protocol.cpp
@@ -0,0 +1,55 @@
+/*
+* Next Protocol Negotation
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/tls_record.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Next_Protocol::Next_Protocol(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::string& protocol) :
+ m_protocol(protocol)
+ {
+ hash.update(writer.send(*this));
+ }
+
+Next_Protocol::Next_Protocol(const std::vector<byte>& buf)
+ {
+ TLS_Data_Reader reader(buf);
+
+ m_protocol = reader.get_string(1, 0, 255);
+
+ reader.get_range_vector<byte>(1, 0, 255); // padding, ignored
+ }
+
+std::vector<byte> Next_Protocol::serialize() const
+ {
+ std::vector<byte> buf;
+
+ append_tls_length_value(buf,
+ reinterpret_cast<const byte*>(m_protocol.data()),
+ m_protocol.size(),
+ 1);
+
+ const byte padding_len = 32 - ((m_protocol.size() + 2) % 32);
+
+ buf.push_back(padding_len);
+
+ for(size_t i = 0; i != padding_len; ++i)
+ buf.push_back(0);
+
+ return buf;
+ }
+
+}
+
+}
diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp
new file mode 100644
index 000000000..fd57496c8
--- /dev/null
+++ b/src/tls/rec_read.cpp
@@ -0,0 +1,353 @@
+/*
+* TLS Record Reading
+* (C) 2004-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_record.h>
+#include <botan/lookup.h>
+#include <botan/loadstor.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/rounding.h>
+#include <botan/internal/assert.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Record_Reader::Record_Reader() :
+ m_readbuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE),
+ m_mac(nullptr)
+ {
+ reset();
+ set_maximum_fragment_size(0);
+ }
+
+/*
+* Reset the state
+*/
+void Record_Reader::reset()
+ {
+ m_macbuf.clear();
+
+ zeroise(m_readbuf);
+ m_readbuf_pos = 0;
+
+ m_cipher.reset();
+
+ delete m_mac;
+ m_mac = nullptr;
+
+ m_block_size = 0;
+ m_iv_size = 0;
+ m_version = Protocol_Version();
+ m_seq_no = 0;
+ set_maximum_fragment_size(0);
+ }
+
+void Record_Reader::set_maximum_fragment_size(size_t max_fragment)
+ {
+ if(max_fragment == 0)
+ m_max_fragment = MAX_PLAINTEXT_SIZE;
+ else
+ m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE);
+ }
+
+/*
+* Set the version to use
+*/
+void Record_Reader::set_version(Protocol_Version version)
+ {
+ m_version = version;
+ }
+
+/*
+* Set the keys for reading
+*/
+void Record_Reader::activate(Connection_Side side,
+ const Ciphersuite& suite,
+ const Session_Keys& keys,
+ byte compression_method)
+ {
+ m_cipher.reset();
+ delete m_mac;
+ m_mac = nullptr;
+ m_seq_no = 0;
+
+ if(compression_method != NO_COMPRESSION)
+ throw Internal_Error("Negotiated unknown compression algorithm");
+
+ SymmetricKey mac_key, cipher_key;
+ InitializationVector iv;
+
+ if(side == CLIENT)
+ {
+ cipher_key = keys.server_cipher_key();
+ iv = keys.server_iv();
+ mac_key = keys.server_mac_key();
+ }
+ else
+ {
+ cipher_key = keys.client_cipher_key();
+ iv = keys.client_iv();
+ mac_key = keys.client_mac_key();
+ }
+
+ const std::string cipher_algo = suite.cipher_algo();
+ const std::string mac_algo = suite.mac_algo();
+
+ if(have_block_cipher(cipher_algo))
+ {
+ m_cipher.append(get_cipher(
+ cipher_algo + "/CBC/NoPadding",
+ cipher_key, iv, DECRYPTION)
+ );
+ m_block_size = block_size_of(cipher_algo);
+
+ if(m_version >= Protocol_Version::TLS_V11)
+ m_iv_size = m_block_size;
+ else
+ m_iv_size = 0;
+ }
+ else if(have_stream_cipher(cipher_algo))
+ {
+ m_cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION));
+ m_block_size = 0;
+ m_iv_size = 0;
+ }
+ else
+ throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo);
+
+ if(have_hash(mac_algo))
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(m_version == Protocol_Version::SSL_V3)
+ m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
+ else
+ m_mac = af.make_mac("HMAC(" + mac_algo + ")");
+
+ m_mac->set_key(mac_key);
+ m_macbuf.resize(m_mac->output_length());
+ }
+ else
+ throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo);
+ }
+
+size_t Record_Reader::fill_buffer_to(const byte*& input,
+ size_t& input_size,
+ size_t& input_consumed,
+ size_t desired)
+ {
+ if(desired <= m_readbuf_pos)
+ return 0; // already have it
+
+ const size_t space_available = (m_readbuf.size() - m_readbuf_pos);
+ const size_t taken = std::min(input_size, desired - m_readbuf_pos);
+
+ if(taken > space_available)
+ throw TLS_Exception(Alert::RECORD_OVERFLOW,
+ "Record is larger than allowed maximum size");
+
+ copy_mem(&m_readbuf[m_readbuf_pos], input, taken);
+ m_readbuf_pos += taken;
+ input_consumed += taken;
+ input_size -= taken;
+ input += taken;
+
+ return (desired - m_readbuf_pos); // how many bytes do we still need?
+ }
+
+/*
+* Retrieve the next record
+*/
+size_t Record_Reader::add_input(const byte input_array[], size_t input_sz,
+ size_t& consumed,
+ byte& msg_type,
+ std::vector<byte>& msg)
+ {
+ const byte* input = &input_array[0];
+
+ consumed = 0;
+
+ if(m_readbuf_pos < TLS_HEADER_SIZE) // header incomplete?
+ {
+ if(size_t needed = fill_buffer_to(input, input_sz, consumed, TLS_HEADER_SIZE))
+ return needed;
+
+ BOTAN_ASSERT_EQUAL(m_readbuf_pos, TLS_HEADER_SIZE,
+ "Have an entire header");
+ }
+
+ // Possible SSLv2 format client hello
+ if((!m_mac) && (m_readbuf[0] & 0x80) && (m_readbuf[2] == 1))
+ {
+ if(m_readbuf[3] == 0 && m_readbuf[4] == 2)
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Client claims to only support SSLv2, rejecting");
+
+ if(m_readbuf[3] >= 3) // SSLv2 mapped TLS hello, then?
+ {
+ size_t record_len = make_u16bit(m_readbuf[0], m_readbuf[1]) & 0x7FFF;
+
+ if(size_t needed = fill_buffer_to(input, input_sz, consumed, record_len + 2))
+ return needed;
+
+ BOTAN_ASSERT_EQUAL(m_readbuf_pos, (record_len + 2),
+ "Have the entire SSLv2 hello");
+
+ msg_type = HANDSHAKE;
+
+ msg.resize(record_len + 4);
+
+ // Fake v3-style handshake message wrapper
+ msg[0] = CLIENT_HELLO_SSLV2;
+ msg[1] = 0;
+ msg[2] = m_readbuf[0] & 0x7F;
+ msg[3] = m_readbuf[1];
+
+ copy_mem(&msg[4], &m_readbuf[2], m_readbuf_pos - 2);
+ m_readbuf_pos = 0;
+ return 0;
+ }
+ }
+
+ if(m_readbuf[0] != CHANGE_CIPHER_SPEC &&
+ m_readbuf[0] != ALERT &&
+ m_readbuf[0] != HANDSHAKE &&
+ m_readbuf[0] != APPLICATION_DATA &&
+ m_readbuf[0] != HEARTBEAT)
+ {
+ throw Unexpected_Message(
+ "Unknown record type " + std::to_string(m_readbuf[0]) +
+ " from counterparty");
+ }
+
+ const size_t record_len = make_u16bit(m_readbuf[3], m_readbuf[4]);
+
+ if(m_version.major_version())
+ {
+ if(m_readbuf[1] != m_version.major_version() ||
+ m_readbuf[2] != m_version.minor_version())
+ {
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Got unexpected version from counterparty");
+ }
+ }
+
+ if(record_len > MAX_CIPHERTEXT_SIZE)
+ throw TLS_Exception(Alert::RECORD_OVERFLOW,
+ "Got message that exceeds maximum size");
+
+ if(size_t needed = fill_buffer_to(input, input_sz, consumed,
+ TLS_HEADER_SIZE + record_len))
+ return needed;
+
+ BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_len,
+ m_readbuf_pos,
+ "Have the full record");
+
+ // Null mac means no encryption either, only valid during handshake
+ if(!m_mac)
+ {
+ if(m_readbuf[0] != CHANGE_CIPHER_SPEC &&
+ m_readbuf[0] != ALERT &&
+ m_readbuf[0] != HANDSHAKE)
+ {
+ throw Decoding_Error("Invalid msg type received during handshake");
+ }
+
+ msg_type = m_readbuf[0];
+ msg.resize(record_len);
+ copy_mem(&msg[0], &m_readbuf[TLS_HEADER_SIZE], record_len);
+
+ m_readbuf_pos = 0;
+ return 0; // got a full record
+ }
+
+ // Otherwise, decrypt, check MAC, return plaintext
+
+ // FIXME: avoid memory allocation by processing in place
+ m_cipher.process_msg(&m_readbuf[TLS_HEADER_SIZE], record_len);
+ size_t got_back = m_cipher.read(&m_readbuf[TLS_HEADER_SIZE], record_len, Pipe::LAST_MESSAGE);
+ BOTAN_ASSERT_EQUAL(got_back, record_len, "Cipher encrypted full amount");
+
+ BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0,
+ "Cipher had no remaining inputs");
+
+ size_t pad_size = 0;
+
+ if(m_block_size)
+ {
+ byte pad_value = m_readbuf[TLS_HEADER_SIZE + (record_len-1)];
+ pad_size = pad_value + 1;
+
+ /*
+ * Check the padding; if it is wrong, then say we have 0 bytes of
+ * padding, which should ensure that the MAC check below does not
+ * succeed. This hides a timing channel.
+ *
+ * This particular countermeasure is recommended in the TLS 1.2
+ * spec (RFC 5246) in section 6.2.3.2
+ */
+ if(m_version == Protocol_Version::SSL_V3)
+ {
+ if(pad_value > m_block_size)
+ pad_size = 0;
+ }
+ else
+ {
+ bool padding_good = true;
+
+ for(size_t i = 0; i != pad_size; ++i)
+ if(m_readbuf[TLS_HEADER_SIZE + (record_len-i-1)] != pad_value)
+ padding_good = false;
+
+ if(!padding_good)
+ pad_size = 0;
+ }
+ }
+
+ const size_t mac_pad_iv_size = m_macbuf.size() + pad_size + m_iv_size;
+
+ if(record_len < mac_pad_iv_size)
+ throw Decoding_Error("Record sent with invalid length");
+
+ const u16bit plain_length = record_len - mac_pad_iv_size;
+
+ if(plain_length > m_max_fragment)
+ throw TLS_Exception(Alert::RECORD_OVERFLOW, "Plaintext record is too large");
+
+ m_mac->update_be(m_seq_no);
+ m_mac->update(m_readbuf[0]); // msg_type
+
+ if(m_version != Protocol_Version::SSL_V3)
+ {
+ m_mac->update(m_version.major_version());
+ m_mac->update(m_version.minor_version());
+ }
+
+ m_mac->update_be(plain_length);
+ m_mac->update(&m_readbuf[TLS_HEADER_SIZE + m_iv_size], plain_length);
+
+ ++m_seq_no;
+
+ m_mac->final(&m_macbuf[0]);
+
+ const size_t mac_offset = record_len - (m_macbuf.size() + pad_size);
+
+ if(!same_mem(&m_readbuf[TLS_HEADER_SIZE + mac_offset], &m_macbuf[0], m_macbuf.size()))
+ throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
+
+ msg_type = m_readbuf[0];
+
+ msg.resize(plain_length);
+ copy_mem(&msg[0], &m_readbuf[TLS_HEADER_SIZE + m_iv_size], plain_length);
+ m_readbuf_pos = 0;
+ return 0;
+ }
+
+}
+
+}
diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp
new file mode 100644
index 000000000..d18ab6594
--- /dev/null
+++ b/src/tls/rec_wri.cpp
@@ -0,0 +1,317 @@
+/*
+* TLS Record Writing
+* (C) 2004-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_record.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_handshake_hash.h>
+#include <botan/lookup.h>
+#include <botan/internal/rounding.h>
+#include <botan/internal/assert.h>
+#include <botan/loadstor.h>
+#include <botan/libstate.h>
+
+namespace Botan {
+
+namespace TLS {
+
+/*
+* Record_Writer Constructor
+*/
+Record_Writer::Record_Writer(std::function<void (const byte[], size_t)> out) :
+ m_output_fn(out),
+ m_writebuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE),
+ m_mac(nullptr)
+ {
+ reset();
+ set_maximum_fragment_size(0);
+ }
+
+void Record_Writer::set_maximum_fragment_size(size_t max_fragment)
+ {
+ if(max_fragment == 0)
+ m_max_fragment = MAX_PLAINTEXT_SIZE;
+ else
+ m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE);
+ }
+
+/*
+* Reset the state
+*/
+void Record_Writer::reset()
+ {
+ set_maximum_fragment_size(0);
+ m_cipher.reset();
+
+ delete m_mac;
+ m_mac = nullptr;
+
+ m_version = Protocol_Version();
+ m_block_size = 0;
+ m_mac_size = 0;
+ m_iv_size = 0;
+
+ m_seq_no = 0;
+ }
+
+/*
+* Set the version to use
+*/
+void Record_Writer::set_version(Protocol_Version version)
+ {
+ m_version = version;
+ }
+
+/*
+* Set the keys for writing
+*/
+void Record_Writer::activate(Connection_Side side,
+ const Ciphersuite& suite,
+ const Session_Keys& keys,
+ byte compression_method)
+ {
+ m_cipher.reset();
+ delete m_mac;
+ m_mac = nullptr;
+
+ if(compression_method != NO_COMPRESSION)
+ throw Internal_Error("Negotiated unknown compression algorithm");
+
+ /*
+ RFC 4346:
+ A sequence number is incremented after each record: specifically,
+ the first record transmitted under a particular connection state
+ MUST use sequence number 0
+ */
+ m_seq_no = 0;
+
+ SymmetricKey mac_key, cipher_key;
+ InitializationVector iv;
+
+ if(side == CLIENT)
+ {
+ cipher_key = keys.client_cipher_key();
+ iv = keys.client_iv();
+ mac_key = keys.client_mac_key();
+ }
+ else
+ {
+ cipher_key = keys.server_cipher_key();
+ iv = keys.server_iv();
+ mac_key = keys.server_mac_key();
+ }
+
+ const std::string cipher_algo = suite.cipher_algo();
+ const std::string mac_algo = suite.mac_algo();
+
+ if(have_block_cipher(cipher_algo))
+ {
+ m_cipher.append(get_cipher(
+ cipher_algo + "/CBC/NoPadding",
+ cipher_key, iv, ENCRYPTION)
+ );
+ m_block_size = block_size_of(cipher_algo);
+
+ if(m_version >= Protocol_Version::TLS_V11)
+ m_iv_size = m_block_size;
+ else
+ m_iv_size = 0;
+ }
+ else if(have_stream_cipher(cipher_algo))
+ {
+ m_cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION));
+ m_block_size = 0;
+ m_iv_size = 0;
+ }
+ else
+ throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo);
+
+ if(have_hash(mac_algo))
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(m_version == Protocol_Version::SSL_V3)
+ m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
+ else
+ m_mac = af.make_mac("HMAC(" + mac_algo + ")");
+
+ m_mac->set_key(mac_key);
+ m_mac_size = m_mac->output_length();
+ }
+ else
+ throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo);
+ }
+
+std::vector<byte> Record_Writer::send(Handshake_Message& msg)
+ {
+ const std::vector<byte> buf = msg.serialize();
+ std::vector<byte> send_buf(4);
+
+ const size_t buf_size = buf.size();
+
+ send_buf[0] = msg.type();
+
+ for(size_t i = 1; i != 4; ++i)
+ send_buf[i] = get_byte<u32bit>(i, buf_size);
+
+ send_buf += buf;
+
+ send(HANDSHAKE, &send_buf[0], send_buf.size());
+
+ return send_buf;
+ }
+
+/*
+* Send one or more records to the other side
+*/
+void Record_Writer::send(byte type, const byte input[], size_t length)
+ {
+ if(length == 0)
+ return;
+
+ /*
+ * If using CBC mode in SSLv3/TLS v1.0, send a single byte of
+ * plaintext to randomize the (implicit) IV of the following main
+ * block. If using a stream cipher, or TLS v1.1, this isn't
+ * necessary.
+ *
+ * An empty record also works but apparently some implementations do
+ * not like this (https://bugzilla.mozilla.org/show_bug.cgi?id=665814)
+ *
+ * See http://www.openssl.org/~bodo/tls-cbc.txt for background.
+ */
+ if((type == APPLICATION) && (m_block_size > 0) && (m_iv_size == 0))
+ {
+ send_record(type, &input[0], 1);
+ input += 1;
+ length -= 1;
+ }
+
+ while(length)
+ {
+ const size_t sending = std::min(length, m_max_fragment);
+ send_record(type, &input[0], sending);
+
+ input += sending;
+ length -= sending;
+ }
+ }
+
+/*
+* Encrypt and send the record
+*/
+void Record_Writer::send_record(byte type, const byte input[], size_t length)
+ {
+ if(length >= MAX_PLAINTEXT_SIZE)
+ throw Internal_Error("Record_Writer: Compressed packet is too big");
+
+ if(m_mac_size == 0) // initial unencrypted handshake records
+ {
+ m_writebuf[0] = type;
+ m_writebuf[1] = m_version.major_version();
+ m_writebuf[2] = m_version.minor_version();
+ m_writebuf[3] = get_byte<u16bit>(0, length);
+ m_writebuf[4] = get_byte<u16bit>(1, length);
+
+ copy_mem(&m_writebuf[TLS_HEADER_SIZE], input, length);
+
+ m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + length);
+ return;
+ }
+
+ m_mac->update_be(m_seq_no);
+ m_mac->update(type);
+
+ if(m_version != Protocol_Version::SSL_V3)
+ {
+ m_mac->update(m_version.major_version());
+ m_mac->update(m_version.minor_version());
+ }
+
+ m_mac->update(get_byte<u16bit>(0, length));
+ m_mac->update(get_byte<u16bit>(1, length));
+ m_mac->update(input, length);
+
+ const size_t buf_size = round_up(m_iv_size + length +
+ m_mac->output_length() +
+ (m_block_size ? 1 : 0),
+ m_block_size);
+
+ if(buf_size >= MAX_CIPHERTEXT_SIZE)
+ throw Internal_Error("Record_Writer: Record is too big");
+
+ BOTAN_ASSERT(m_writebuf.size() >= TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE,
+ "Write buffer is big enough");
+
+ // TLS record header
+ m_writebuf[0] = type;
+ m_writebuf[1] = m_version.major_version();
+ m_writebuf[2] = m_version.minor_version();
+ m_writebuf[3] = get_byte<u16bit>(0, buf_size);
+ m_writebuf[4] = get_byte<u16bit>(1, buf_size);
+
+ byte* buf_write_ptr = &m_writebuf[TLS_HEADER_SIZE];
+
+ if(m_iv_size)
+ {
+ RandomNumberGenerator& rng = global_state().global_rng();
+ rng.randomize(buf_write_ptr, m_iv_size);
+ buf_write_ptr += m_iv_size;
+ }
+
+ copy_mem(buf_write_ptr, input, length);
+ buf_write_ptr += length;
+
+ m_mac->final(buf_write_ptr);
+ buf_write_ptr += m_mac->output_length();
+
+ if(m_block_size)
+ {
+ const size_t pad_val =
+ buf_size - (m_iv_size + length + m_mac->output_length() + 1);
+
+ for(size_t i = 0; i != pad_val + 1; ++i)
+ {
+ *buf_write_ptr = pad_val;
+ buf_write_ptr += 1;
+ }
+ }
+
+ // FIXME: this could be done in-place without copying
+ m_cipher.process_msg(&m_writebuf[TLS_HEADER_SIZE], buf_size);
+
+ const size_t ctext_size = m_cipher.remaining(Pipe::LAST_MESSAGE);
+
+ BOTAN_ASSERT_EQUAL(ctext_size, buf_size, "Cipher encrypted full amount");
+
+ if(ctext_size > MAX_CIPHERTEXT_SIZE)
+ throw Internal_Error("Produced ciphertext larger than protocol allows");
+
+ m_cipher.read(&m_writebuf[TLS_HEADER_SIZE], ctext_size, Pipe::LAST_MESSAGE);
+
+ BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0,
+ "No data remains in pipe");
+
+ m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + buf_size);
+
+ m_seq_no++;
+ }
+
+/*
+* Send an alert
+*/
+void Record_Writer::send_alert(const Alert& alert)
+ {
+ const byte alert_bits[2] = { static_cast<byte>(alert.is_fatal() ? 2 : 1),
+ static_cast<byte>(alert.type()) };
+
+ send(ALERT, alert_bits, sizeof(alert_bits));
+ }
+
+}
+
+}
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp
new file mode 100644
index 000000000..d4cc4a1ab
--- /dev/null
+++ b/src/tls/s_hello.cpp
@@ -0,0 +1,186 @@
+;/*
+* TLS Server Hello and Server Hello Done
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/stl_util.h>
+
+namespace Botan {
+
+namespace TLS {
+
+/*
+* Create a new Server Hello message
+*/
+Server_Hello::Server_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<byte>& session_id,
+ Protocol_Version ver,
+ u16bit ciphersuite,
+ byte compression,
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const std::vector<byte>& reneg_info,
+ bool offer_session_ticket,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ bool client_has_heartbeat,
+ RandomNumberGenerator& rng) :
+ m_version(ver),
+ m_session_id(session_id),
+ m_random(make_hello_random(rng)),
+ m_ciphersuite(ciphersuite),
+ m_comp_method(compression),
+ m_fragment_size(max_fragment_size),
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(client_has_npn),
+ m_next_protocols(next_protocols),
+ m_supports_session_ticket(offer_session_ticket),
+ m_supports_heartbeats(client_has_heartbeat),
+ m_peer_can_send_heartbeats(true)
+ {
+ hash.update(writer.send(*this));
+ }
+
+/*
+* Deserialize a Server Hello message
+*/
+Server_Hello::Server_Hello(const std::vector<byte>& buf)
+ {
+ m_secure_renegotiation = false;
+ m_supports_session_ticket = false;
+ m_next_protocol = false;
+
+ if(buf.size() < 38)
+ throw Decoding_Error("Server_Hello: Packet corrupted");
+
+ TLS_Data_Reader reader(buf);
+
+ const byte major_version = reader.get_byte();
+ const byte minor_version = reader.get_byte();
+
+ m_version = Protocol_Version(major_version, minor_version);
+
+ if(m_version != Protocol_Version::SSL_V3 &&
+ m_version != Protocol_Version::TLS_V10 &&
+ m_version != Protocol_Version::TLS_V11 &&
+ m_version != Protocol_Version::TLS_V12)
+ {
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Server_Hello: Unsupported server version");
+ }
+
+ m_random = reader.get_fixed<byte>(32);
+
+ m_session_id = reader.get_range<byte>(1, 0, 32);
+
+ m_ciphersuite = reader.get_u16bit();
+
+ m_comp_method = reader.get_byte();
+
+ Extensions extensions(reader);
+
+ if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>())
+ {
+ // checked by Client / Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+
+ if(Next_Protocol_Notification* npn = extensions.get<Next_Protocol_Notification>())
+ {
+ m_next_protocols = npn->protocols();
+ m_next_protocol = true;
+ }
+
+ if(Session_Ticket* ticket = extensions.get<Session_Ticket>())
+ {
+ if(!ticket->contents().empty())
+ throw Decoding_Error("TLS server sent non-empty session ticket extension");
+ m_supports_session_ticket = true;
+ }
+
+ if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>())
+ {
+ m_supports_heartbeats = true;
+ m_peer_can_send_heartbeats = hb->peer_allowed_to_send();
+ }
+ }
+
+/*
+* Serialize a Server Hello message
+*/
+std::vector<byte> Server_Hello::serialize() const
+ {
+ std::vector<byte> buf;
+
+ buf.push_back(m_version.major_version());
+ buf.push_back(m_version.minor_version());
+ buf += m_random;
+
+ append_tls_length_value(buf, m_session_id, 1);
+
+ buf.push_back(get_byte(0, m_ciphersuite));
+ buf.push_back(get_byte(1, m_ciphersuite));
+
+ buf.push_back(m_comp_method);
+
+ Extensions extensions;
+
+ if(m_supports_heartbeats)
+ extensions.add(new Heartbeat_Support_Indicator(m_peer_can_send_heartbeats));
+
+ if(m_secure_renegotiation)
+ extensions.add(new Renegotation_Extension(m_renegotiation_info));
+
+ if(m_fragment_size != 0)
+ extensions.add(new Maximum_Fragment_Length(m_fragment_size));
+
+ if(m_next_protocol)
+ extensions.add(new Next_Protocol_Notification(m_next_protocols));
+
+ if(m_supports_session_ticket)
+ extensions.add(new Session_Ticket());
+
+ buf += extensions.serialize();
+
+ return buf;
+ }
+
+/*
+* Create a new Server Hello Done message
+*/
+Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
+ Handshake_Hash& hash)
+ {
+ hash.update(writer.send(*this));
+ }
+
+/*
+* Deserialize a Server Hello Done message
+*/
+Server_Hello_Done::Server_Hello_Done(const std::vector<byte>& buf)
+ {
+ if(buf.size())
+ throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
+ }
+
+/*
+* Serialize a Server Hello Done message
+*/
+std::vector<byte> Server_Hello_Done::serialize() const
+ {
+ return std::vector<byte>();
+ }
+
+}
+
+}
diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp
new file mode 100644
index 000000000..48901d311
--- /dev/null
+++ b/src/tls/s_kex.cpp
@@ -0,0 +1,292 @@
+/*
+* Server Key Exchange Message
+* (C) 2004-2010,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/assert.h>
+#include <botan/credentials_manager.h>
+#include <botan/loadstor.h>
+#include <botan/pubkey.h>
+#include <botan/dh.h>
+#include <botan/ecdh.h>
+#include <botan/rsa.h>
+#include <botan/srp6.h>
+#include <botan/oids.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Create a new Server Key Exchange message
+*/
+Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer,
+ Handshake_State* state,
+ const Policy& policy,
+ Credentials_Manager& creds,
+ RandomNumberGenerator& rng,
+ const Private_Key* signing_key) :
+ m_kex_key(nullptr), m_srp_params(nullptr)
+ {
+ const std::string hostname = state->client_hello->sni_hostname();
+ const std::string kex_algo = state->suite.kex_algo();
+
+ if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
+ {
+ std::string identity_hint =
+ creds.psk_identity_hint("tls-server", hostname);
+
+ append_tls_length_value(m_params, identity_hint, 2);
+ }
+
+ if(kex_algo == "DH" || kex_algo == "DHE_PSK")
+ {
+ std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, policy.dh_group()));
+
+ append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
+ append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
+ append_tls_length_value(m_params, dh->public_value(), 2);
+ m_kex_key = dh.release();
+ }
+ else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
+ {
+ const std::vector<std::string>& curves =
+ state->client_hello->supported_ecc_curves();
+
+ if(curves.empty())
+ throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
+
+ const std::string curve_name = policy.choose_curve(curves);
+
+ if(curve_name == "")
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Could not agree on an ECC curve with the client");
+
+ EC_Group ec_group(curve_name);
+
+ std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group));
+
+ const std::string ecdh_domain_oid = ecdh->domain().get_oid();
+ const std::string domain = OIDS::lookup(OID(ecdh_domain_oid));
+
+ if(domain == "")
+ throw Internal_Error("Could not find name of ECDH domain " + ecdh_domain_oid);
+
+ const u16bit named_curve_id = Supported_Elliptic_Curves::name_to_curve_id(domain);
+
+ m_params.push_back(3); // named curve
+ m_params.push_back(get_byte(0, named_curve_id));
+ m_params.push_back(get_byte(1, named_curve_id));
+
+ append_tls_length_value(m_params, ecdh->public_value(), 1);
+
+ m_kex_key = ecdh.release();
+ }
+ else if(kex_algo == "SRP_SHA")
+ {
+ const std::string srp_identifier = state->client_hello->srp_identifier();
+
+ std::string group_id;
+ BigInt v;
+ std::vector<byte> salt;
+
+ const bool found = creds.srp_verifier("tls-server", hostname,
+ srp_identifier,
+ group_id, v, salt,
+ policy.hide_unknown_users());
+
+ if(!found)
+ throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
+ "Unknown SRP user " + srp_identifier);
+
+ m_srp_params = new SRP6_Server_Session;
+
+ BigInt B = m_srp_params->step1(v, group_id,
+ "SHA-1", rng);
+
+ DL_Group group(group_id);
+
+ append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2);
+ append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2);
+ append_tls_length_value(m_params, salt, 1);
+ append_tls_length_value(m_params, BigInt::encode(B), 2);
+ }
+ else if(kex_algo != "PSK")
+ throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo);
+
+ if(state->suite.sig_algo() != "")
+ {
+ BOTAN_ASSERT(signing_key, "No signing key set");
+
+ std::pair<std::string, Signature_Format> format =
+ state->choose_sig_format(signing_key, m_hash_algo, m_sig_algo, false);
+
+ PK_Signer signer(*signing_key, format.first, format.second);
+
+ signer.update(state->client_hello->random());
+ signer.update(state->server_hello->random());
+ signer.update(params());
+ m_signature = signer.signature(rng);
+ }
+
+ state->hash.update(writer.send(*this));
+ }
+
+/**
+* Deserialize a Server Key Exchange message
+*/
+Server_Key_Exchange::Server_Key_Exchange(const std::vector<byte>& buf,
+ const std::string& kex_algo,
+ const std::string& sig_algo,
+ Protocol_Version version) :
+ m_kex_key(nullptr), m_srp_params(nullptr)
+ {
+ if(buf.size() < 6)
+ throw Decoding_Error("Server_Key_Exchange: Packet corrupted");
+
+ TLS_Data_Reader reader(buf);
+
+ /*
+ * We really are just serializing things back to what they were
+ * before, but unfortunately to know where the signature is we need
+ * to be able to parse the whole thing anyway.
+ */
+
+ if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
+ {
+ const std::string identity_hint = reader.get_string(2, 0, 65535);
+ append_tls_length_value(m_params, identity_hint, 2);
+ }
+
+ if(kex_algo == "DH" || kex_algo == "DHE_PSK")
+ {
+ // 3 bigints, DH p, g, Y
+
+ for(size_t i = 0; i != 3; ++i)
+ {
+ BigInt v = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ append_tls_length_value(m_params, BigInt::encode(v), 2);
+ }
+ }
+ else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
+ {
+ const byte curve_type = reader.get_byte();
+
+ if(curve_type != 3)
+ throw Decoding_Error("Server_Key_Exchange: Server sent non-named ECC curve");
+
+ const u16bit curve_id = reader.get_u16bit();
+
+ const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);
+
+ std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);
+
+ if(name == "")
+ throw Decoding_Error("Server_Key_Exchange: Server sent unknown named curve " +
+ std::to_string(curve_id));
+
+ m_params.push_back(curve_type);
+ m_params.push_back(get_byte(0, curve_id));
+ m_params.push_back(get_byte(1, curve_id));
+ append_tls_length_value(m_params, ecdh_key, 1);
+ }
+ else if(kex_algo == "SRP_SHA")
+ {
+ // 2 bigints (N,g) then salt, then server B
+
+ const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+ std::vector<byte> salt = reader.get_range<byte>(1, 1, 255);
+ const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
+
+ append_tls_length_value(m_params, BigInt::encode(N), 2);
+ append_tls_length_value(m_params, BigInt::encode(g), 2);
+ append_tls_length_value(m_params, salt, 1);
+ append_tls_length_value(m_params, BigInt::encode(B), 2);
+ }
+ else if(kex_algo != "PSK")
+ throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo);
+
+ if(sig_algo != "")
+ {
+ if(version >= Protocol_Version::TLS_V12)
+ {
+ m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte());
+ m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte());
+ }
+
+ m_signature = reader.get_range<byte>(2, 0, 65535);
+ }
+ }
+
+Server_Key_Exchange::~Server_Key_Exchange()
+ {
+ delete m_kex_key;
+ delete m_srp_params;
+ }
+
+
+/**
+* Serialize a Server Key Exchange message
+*/
+std::vector<byte> Server_Key_Exchange::serialize() const
+ {
+ std::vector<byte> buf = params();
+
+ if(m_signature.size())
+ {
+ // This should be an explicit version check
+ if(m_hash_algo != "" && m_sig_algo != "")
+ {
+ buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
+ buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
+ }
+
+ append_tls_length_value(buf, m_signature, 2);
+ }
+
+ return buf;
+ }
+
+/**
+* Verify a Server Key Exchange message
+*/
+bool Server_Key_Exchange::verify(const X509_Certificate& cert,
+ Handshake_State* state) const
+ {
+ std::unique_ptr<Public_Key> key(cert.subject_public_key());
+
+ std::pair<std::string, Signature_Format> format =
+ state->understand_sig_format(key.get(), m_hash_algo, m_sig_algo, false);
+
+ PK_Verifier verifier(*key, format.first, format.second);
+
+ verifier.update(state->client_hello->random());
+ verifier.update(state->server_hello->random());
+ verifier.update(params());
+
+ return verifier.check_signature(m_signature);
+ }
+
+const Private_Key& Server_Key_Exchange::server_kex_key() const
+ {
+ BOTAN_ASSERT(m_kex_key, "Key is non-NULL");
+ return *m_kex_key;
+ }
+
+// Only valid for SRP negotiation
+SRP6_Server_Session& Server_Key_Exchange::server_srp_params()
+ {
+ BOTAN_ASSERT(m_srp_params, "SRP params are non-NULL");
+ return *m_srp_params;
+ }
+}
+
+}
diff --git a/src/tls/session_ticket.cpp b/src/tls/session_ticket.cpp
new file mode 100644
index 000000000..8cee2a454
--- /dev/null
+++ b/src/tls/session_ticket.cpp
@@ -0,0 +1,57 @@
+/*
+* Session Tickets
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/tls_record.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace TLS {
+
+New_Session_Ticket::New_Session_Ticket(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<byte>& ticket,
+ u32bit lifetime) :
+ m_ticket_lifetime_hint(lifetime),
+ m_ticket(ticket)
+ {
+ hash.update(writer.send(*this));
+ }
+
+New_Session_Ticket::New_Session_Ticket(Record_Writer& writer,
+ Handshake_Hash& hash) :
+ m_ticket_lifetime_hint(0)
+ {
+ hash.update(writer.send(*this));
+ }
+
+New_Session_Ticket::New_Session_Ticket(const std::vector<byte>& buf) :
+ m_ticket_lifetime_hint(0)
+ {
+ if(buf.size() < 6)
+ throw Decoding_Error("Session ticket message too short to be valid");
+
+ TLS_Data_Reader reader(buf);
+
+ m_ticket_lifetime_hint = reader.get_u32bit();
+ m_ticket = reader.get_range<byte>(2, 0, 65535);
+ }
+
+std::vector<byte> New_Session_Ticket::serialize() const
+ {
+ std::vector<byte> buf(4);
+ store_be(m_ticket_lifetime_hint, &buf[0]);
+ append_tls_length_value(buf, m_ticket, 2);
+ return buf;
+ }
+
+}
+
+}
diff --git a/src/tls/sessions_sqlite/info.txt b/src/tls/sessions_sqlite/info.txt
new file mode 100644
index 000000000..c5fc35952
--- /dev/null
+++ b/src/tls/sessions_sqlite/info.txt
@@ -0,0 +1,11 @@
+define TLS_SQLITE_SESSION_MANAGER
+
+load_on request
+
+<libs>
+all -> sqlite3
+</libs>
+
+<requires>
+pbkdf2
+</requires>
diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp
new file mode 100644
index 000000000..b6aaa3498
--- /dev/null
+++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp
@@ -0,0 +1,350 @@
+/*
+* SQLite TLS Session Manager
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_sqlite_sess_mgr.h>
+#include <botan/internal/assert.h>
+#include <botan/lookup.h>
+#include <botan/hex.h>
+#include <botan/loadstor.h>
+#include <memory>
+#include <chrono>
+
+#include <sqlite3.h>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+class sqlite3_statement
+ {
+ public:
+ sqlite3_statement(sqlite3* db, const std::string& base_sql)
+ {
+ int rc = sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, 0);
+
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_prepare failed " + base_sql +
+ ", code " + std::to_string(rc));
+ }
+
+ void bind(int column, const std::string& val)
+ {
+ int rc = sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc));
+ }
+
+ void bind(int column, int val)
+ {
+ int rc = sqlite3_bind_int(m_stmt, column, val);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc));
+ }
+
+ void bind(int column, std::chrono::system_clock::time_point time)
+ {
+ const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count();
+ bind(column, timeval);
+ }
+
+ void bind(int column, const std::vector<byte>& val)
+ {
+ int rc = sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc));
+ }
+
+ std::pair<const byte*, size_t> get_blob(int column)
+ {
+ BOTAN_ASSERT(sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB,
+ "Return value is a blob");
+
+ const void* session_blob = sqlite3_column_blob(m_stmt, column);
+ const int session_blob_size = sqlite3_column_bytes(m_stmt, column);
+
+ BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative");
+
+ return std::make_pair(static_cast<const byte*>(session_blob),
+ static_cast<size_t>(session_blob_size));
+ }
+
+ size_t get_size_t(int column)
+ {
+ BOTAN_ASSERT(sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER,
+ "Return count is an integer");
+
+ const int sessions_int = sqlite3_column_int(m_stmt, column);
+
+ BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative");
+
+ return static_cast<size_t>(sessions_int);
+ }
+
+ void spin()
+ {
+ while(sqlite3_step(m_stmt) == SQLITE_ROW)
+ {}
+ }
+
+ int step()
+ {
+ return sqlite3_step(m_stmt);
+ }
+
+ sqlite3_stmt* stmt() { return m_stmt; }
+
+ ~sqlite3_statement() { sqlite3_finalize(m_stmt); }
+ private:
+ sqlite3_stmt* m_stmt;
+ };
+
+size_t row_count(sqlite3* db, const std::string& table_name)
+ {
+ sqlite3_statement stmt(db, "select count(*) from " + table_name);
+
+ if(stmt.step() == SQLITE_ROW)
+ return stmt.get_size_t(0);
+ else
+ throw std::runtime_error("Querying size of table " + table_name + " failed");
+ }
+
+void create_table(sqlite3* db, const char* table_schema)
+ {
+ char* errmsg = 0;
+ int rc = sqlite3_exec(db, table_schema, 0, 0, &errmsg);
+
+ if(rc != SQLITE_OK)
+ {
+ const std::string err_msg = errmsg;
+ sqlite3_free(errmsg);
+ sqlite3_close(db);
+ throw std::runtime_error("sqlite3_exec for table failed - " + err_msg);
+ }
+ }
+
+
+SymmetricKey derive_key(const std::string& passphrase,
+ const byte salt[],
+ size_t salt_len,
+ size_t iterations,
+ size_t& check_val)
+ {
+ std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-512)"));
+
+ std::vector<byte> x = pbkdf->derive_key(32 + 3,
+ passphrase,
+ salt, salt_len,
+ iterations).bits_of();
+
+ check_val = make_u32bit(0, x[0], x[1], x[2]);
+ return SymmetricKey(&x[3], x.size() - 3);
+ }
+
+}
+
+Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase,
+ RandomNumberGenerator& rng,
+ const std::string& db_filename,
+ size_t max_sessions,
+ std::chrono::seconds session_lifetime) :
+ m_rng(rng),
+ m_max_sessions(max_sessions),
+ m_session_lifetime(session_lifetime)
+ {
+ int rc = sqlite3_open(db_filename.c_str(), &m_db);
+
+ if(rc)
+ {
+ const std::string err_msg = sqlite3_errmsg(m_db);
+ sqlite3_close(m_db);
+ throw std::runtime_error("sqlite3_open failed - " + err_msg);
+ }
+
+ create_table(m_db,
+ "create table if not exists tls_sessions "
+ "("
+ "session_id TEXT PRIMARY KEY, "
+ "session_start INTEGER, "
+ "hostname TEXT, "
+ "hostport INTEGER, "
+ "session BLOB"
+ ")");
+
+ create_table(m_db,
+ "create table if not exists tls_sessions_metadata "
+ "("
+ "passphrase_salt BLOB, "
+ "passphrase_iterations INTEGER, "
+ "passphrase_check INTEGER "
+ ")");
+
+ const size_t salts = row_count(m_db, "tls_sessions_metadata");
+
+ if(salts == 1)
+ {
+ // existing db
+ sqlite3_statement stmt(m_db, "select * from tls_sessions_metadata");
+
+ int rc = stmt.step();
+ if(rc == SQLITE_ROW)
+ {
+ std::pair<const byte*, size_t> salt = stmt.get_blob(0);
+ const size_t iterations = stmt.get_size_t(1);
+ const size_t check_val_db = stmt.get_size_t(2);
+
+ size_t check_val_created;
+ m_session_key = derive_key(passphrase,
+ salt.first,
+ salt.second,
+ iterations,
+ check_val_created);
+
+ if(check_val_created != check_val_db)
+ throw std::runtime_error("Session database password not valid");
+ }
+ }
+ else
+ {
+ // maybe just zap the salts + sessions tables in this case?
+ if(salts != 0)
+ throw std::runtime_error("Seemingly corrupted database, multiple salts found");
+
+ // new database case
+
+ std::vector<byte> salt = rng.random_vec(16);
+ const size_t iterations = 64 * 1024;
+ size_t check_val = 0;
+
+ m_session_key = derive_key(passphrase, &salt[0], salt.size(),
+ iterations, check_val);
+
+ sqlite3_statement stmt(m_db, "insert into tls_sessions_metadata"
+ " values(?1, ?2, ?3)");
+
+ stmt.bind(1, salt);
+ stmt.bind(2, iterations);
+ stmt.bind(3, check_val);
+
+ stmt.spin();
+ }
+ }
+
+Session_Manager_SQLite::~Session_Manager_SQLite()
+ {
+ sqlite3_close(m_db);
+ }
+
+bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& session_id,
+ Session& session)
+ {
+ sqlite3_statement stmt(m_db, "select session from tls_sessions where session_id = ?1");
+
+ stmt.bind(1, hex_encode(session_id));
+
+ int rc = stmt.step();
+
+ while(rc == SQLITE_ROW)
+ {
+ std::pair<const byte*, size_t> blob = stmt.get_blob(0);
+
+ try
+ {
+ session = Session::decrypt(blob.first, blob.second, m_session_key);
+ return true;
+ }
+ catch(...)
+ {
+ }
+
+ rc = stmt.step();
+ }
+
+ return false;
+ }
+
+bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname,
+ u16bit port,
+ Session& session)
+ {
+ sqlite3_statement stmt(m_db, "select session from tls_sessions"
+ " where hostname = ?1 and hostport = ?2"
+ " order by session_start desc");
+
+ stmt.bind(1, hostname);
+ stmt.bind(2, port);
+
+ int rc = stmt.step();
+
+ while(rc == SQLITE_ROW)
+ {
+ std::pair<const byte*, size_t> blob = stmt.get_blob(0);
+
+ try
+ {
+ session = Session::decrypt(blob.first, blob.second, m_session_key);
+ return true;
+ }
+ catch(...)
+ {
+ }
+
+ rc = stmt.step();
+ }
+
+ return false;
+ }
+
+void Session_Manager_SQLite::remove_entry(const std::vector<byte>& session_id)
+ {
+ sqlite3_statement stmt(m_db, "delete from tls_sessions where session_id = ?1");
+
+ stmt.bind(1, hex_encode(session_id));
+
+ stmt.spin();
+ }
+
+void Session_Manager_SQLite::save(const Session& session)
+ {
+ sqlite3_statement stmt(m_db, "insert or replace into tls_sessions"
+ " values(?1, ?2, ?3, ?4, ?5)");
+
+ stmt.bind(1, hex_encode(session.session_id()));
+ stmt.bind(2, session.start_time());
+ stmt.bind(3, session.sni_hostname());
+ stmt.bind(4, 0);
+ stmt.bind(5, session.encrypt(m_session_key, m_rng));
+
+ stmt.spin();
+
+ prune_session_cache();
+ }
+
+void Session_Manager_SQLite::prune_session_cache()
+ {
+ sqlite3_statement remove_expired(m_db, "delete from tls_sessions where session_start <= ?1");
+
+ remove_expired.bind(1, std::chrono::system_clock::now() - m_session_lifetime);
+
+ remove_expired.spin();
+
+ const size_t sessions = row_count(m_db, "tls_sessions");
+
+ if(sessions > m_max_sessions)
+ {
+ sqlite3_statement remove_some(m_db, "delete from tls_sessions where session_id in "
+ "(select session_id from tls_sessions limit ?1)");
+
+ remove_some.bind(1, sessions - m_max_sessions);
+ remove_some.spin();
+ }
+ }
+
+}
+
+}
diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h
new file mode 100644
index 000000000..923915496
--- /dev/null
+++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h
@@ -0,0 +1,71 @@
+/*
+* SQLite TLS Session Manager
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_SQLITE_SESSION_MANAGER_H__
+#define BOTAN_TLS_SQLITE_SESSION_MANAGER_H__
+
+#include <botan/tls_session_manager.h>
+#include <botan/rng.h>
+
+class sqlite3;
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+*/
+class BOTAN_DLL Session_Manager_SQLite : public Session_Manager
+ {
+ public:
+ /**
+ * @param passphrase used to encrypt the session data
+ * @param db_filename filename of the SQLite database file.
+ The table names tls_sessions and tls_sessions_metadata
+ will be used
+ * @param max_sessions a hint on the maximum number of sessions
+ * to keep in memory at any one time. (If zero, don't cap)
+ * @param session_lifetime sessions are expired after this many
+ * seconds have elapsed from initial handshake.
+ */
+ Session_Manager_SQLite(const std::string& passphrase,
+ RandomNumberGenerator& rng,
+ const std::string& db_filename,
+ size_t max_sessions = 1000,
+ std::chrono::seconds session_lifetime = std::chrono::seconds(7200));
+
+ ~Session_Manager_SQLite();
+
+ bool load_from_session_id(const std::vector<byte>& session_id,
+ Session& session);
+
+ bool load_from_host_info(const std::string& hostname, u16bit port,
+ Session& session);
+
+ void remove_entry(const std::vector<byte>& session_id);
+
+ void save(const Session& session_data);
+
+ std::chrono::seconds session_lifetime() const { return m_session_lifetime; }
+ private:
+ Session_Manager_SQLite(const Session_Manager_SQLite&);
+ Session_Manager_SQLite& operator=(const Session_Manager_SQLite&);
+
+ void prune_session_cache();
+
+ SymmetricKey m_session_key;
+ RandomNumberGenerator& m_rng;
+ size_t m_max_sessions;
+ std::chrono::seconds m_session_lifetime;
+ class sqlite3* m_db;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_alert.cpp b/src/tls/tls_alert.cpp
new file mode 100644
index 000000000..5bc2e7484
--- /dev/null
+++ b/src/tls/tls_alert.cpp
@@ -0,0 +1,122 @@
+/*
+* Alert Message
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_alert.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Alert::Alert(const std::vector<byte>& buf)
+ {
+ if(buf.size() != 2)
+ throw Decoding_Error("Alert: Bad size " + std::to_string(buf.size()) +
+ " for alert message");
+
+ if(buf[0] == 1) fatal = false;
+ else if(buf[0] == 2) fatal = true;
+ else
+ throw Decoding_Error("Alert: Bad code for alert level");
+
+ const byte dc = buf[1];
+
+ /*
+ * This is allowed by the specification but is not allocated and we're
+ * using it internally as a special 'no alert' type.
+ */
+ if(dc == 255)
+ throw Internal_Error("Alert: description code 255, rejecting");
+
+ type_code = static_cast<Type>(dc);
+ }
+
+std::string Alert::type_string() const
+ {
+ switch(type())
+ {
+ case CLOSE_NOTIFY:
+ return "close_notify";
+ case UNEXPECTED_MESSAGE:
+ return "unexpected_message";
+ case BAD_RECORD_MAC:
+ return "bad_record_mac";
+ case DECRYPTION_FAILED:
+ return "decryption_failed";
+ case RECORD_OVERFLOW:
+ return "record_overflow";
+ case DECOMPRESSION_FAILURE:
+ return "decompression_failure";
+ case HANDSHAKE_FAILURE:
+ return "handshake_failure";
+ case NO_CERTIFICATE:
+ return "no_certificate";
+ case BAD_CERTIFICATE:
+ return "bad_certificate";
+ case UNSUPPORTED_CERTIFICATE:
+ return "unsupported_certificate";
+ case CERTIFICATE_REVOKED:
+ return "certificate_revoked";
+ case CERTIFICATE_EXPIRED:
+ return "certificate_expired";
+ case CERTIFICATE_UNKNOWN:
+ return "certificate_unknown";
+ case ILLEGAL_PARAMETER:
+ return "illegal_parameter";
+ case UNKNOWN_CA:
+ return "unknown_ca";
+ case ACCESS_DENIED:
+ return "access_denied";
+ case DECODE_ERROR:
+ return "decode_error";
+ case DECRYPT_ERROR:
+ return "decrypt_error";
+ case EXPORT_RESTRICTION:
+ return "export_restriction";
+ case PROTOCOL_VERSION:
+ return "protocol_version";
+ case INSUFFICIENT_SECURITY:
+ return "insufficient_security";
+ case INTERNAL_ERROR:
+ return "internal_error";
+ case USER_CANCELED:
+ return "user_canceled";
+ case NO_RENEGOTIATION:
+ return "no_renegotiation";
+
+ case UNSUPPORTED_EXTENSION:
+ return "unsupported_extension";
+ case CERTIFICATE_UNOBTAINABLE:
+ return "certificate_unobtainable";
+ case UNRECOGNIZED_NAME:
+ return "unrecognized_name";
+ case BAD_CERTIFICATE_STATUS_RESPONSE:
+ return "bad_certificate_status_response";
+ case BAD_CERTIFICATE_HASH_VALUE:
+ return "bad_certificate_hash_value";
+ case UNKNOWN_PSK_IDENTITY:
+ return "unknown_psk_identity";
+
+ case NULL_ALERT:
+ return "none";
+
+ case HEARTBEAT_PAYLOAD:
+ return "heartbeat_payload";
+ }
+
+ /*
+ * This is effectively the default case for the switch above, but we
+ * leave it out so that when an alert type is added to the enum the
+ * compiler can warn us that it is not included in the switch
+ * statement.
+ */
+ return "unrecognized_alert_" + std::to_string(type());
+ }
+
+}
+
+}
diff --git a/src/tls/tls_alert.h b/src/tls/tls_alert.h
new file mode 100644
index 000000000..b3001f259
--- /dev/null
+++ b/src/tls/tls_alert.h
@@ -0,0 +1,100 @@
+/*
+* Alert Message
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_ALERT_H__
+#define BOTAN_TLS_ALERT_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* SSL/TLS Alert Message
+*/
+class BOTAN_DLL Alert
+ {
+ public:
+ enum Type {
+ CLOSE_NOTIFY = 0,
+ UNEXPECTED_MESSAGE = 10,
+ BAD_RECORD_MAC = 20,
+ DECRYPTION_FAILED = 21,
+ RECORD_OVERFLOW = 22,
+ DECOMPRESSION_FAILURE = 30,
+ HANDSHAKE_FAILURE = 40,
+ NO_CERTIFICATE = 41, // SSLv3 only
+ BAD_CERTIFICATE = 42,
+ UNSUPPORTED_CERTIFICATE = 43,
+ CERTIFICATE_REVOKED = 44,
+ CERTIFICATE_EXPIRED = 45,
+ CERTIFICATE_UNKNOWN = 46,
+ ILLEGAL_PARAMETER = 47,
+ UNKNOWN_CA = 48,
+ ACCESS_DENIED = 49,
+ DECODE_ERROR = 50,
+ DECRYPT_ERROR = 51,
+ EXPORT_RESTRICTION = 60,
+ PROTOCOL_VERSION = 70,
+ INSUFFICIENT_SECURITY = 71,
+ INTERNAL_ERROR = 80,
+ USER_CANCELED = 90,
+ NO_RENEGOTIATION = 100,
+ UNSUPPORTED_EXTENSION = 110,
+ CERTIFICATE_UNOBTAINABLE = 111,
+ UNRECOGNIZED_NAME = 112,
+ BAD_CERTIFICATE_STATUS_RESPONSE = 113,
+ BAD_CERTIFICATE_HASH_VALUE = 114,
+ UNKNOWN_PSK_IDENTITY = 115,
+
+ NULL_ALERT = 255,
+
+ HEARTBEAT_PAYLOAD = 256
+ };
+
+ /**
+ * @return true iff this alert is non-empty
+ */
+ bool is_valid() const { return (type_code != NULL_ALERT); }
+
+ /**
+ * @return if this alert is a fatal one or not
+ */
+ bool is_fatal() const { return fatal; }
+
+ /**
+ * @return type of alert
+ */
+ Type type() const { return type_code; }
+
+ /**
+ * @return type of alert
+ */
+ std::string type_string() const;
+
+ /**
+ * Deserialize an Alert message
+ * @param buf the serialized alert
+ */
+ Alert(const std::vector<byte>& buf);
+
+ Alert(Type alert_type, bool is_fatal = false) :
+ fatal(is_fatal), type_code(alert_type) {}
+
+ Alert() : fatal(false), type_code(NULL_ALERT) {}
+ private:
+ bool fatal;
+ Type type_code;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
new file mode 100644
index 000000000..dadf26e90
--- /dev/null
+++ b/src/tls/tls_channel.cpp
@@ -0,0 +1,326 @@
+/*
+* TLS Channels
+* (C) 2011-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_channel.h>
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_heartbeats.h>
+#include <botan/internal/assert.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Channel::Channel(std::function<void (const byte[], size_t)> socket_output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_complete) :
+ proc_fn(proc_fn),
+ handshake_fn(handshake_complete),
+ writer(socket_output_fn),
+ state(nullptr),
+ handshake_completed(false),
+ connection_closed(false),
+ m_peer_supports_heartbeats(false),
+ m_heartbeat_sending_allowed(false)
+ {
+ }
+
+Channel::~Channel()
+ {
+ delete state;
+ state = nullptr;
+ }
+
+size_t Channel::received_data(const byte buf[], size_t buf_size)
+ {
+ try
+ {
+ while(buf_size)
+ {
+ byte rec_type = CONNECTION_CLOSED;
+ std::vector<byte> record;
+ size_t consumed = 0;
+
+ const size_t needed = reader.add_input(buf, buf_size,
+ consumed,
+ rec_type, record);
+
+ buf += consumed;
+ buf_size -= consumed;
+
+ BOTAN_ASSERT(buf_size == 0 || needed == 0,
+ "Got a full record or consumed all input");
+
+ if(buf_size == 0 && needed != 0)
+ return needed; // need more data to complete record
+
+ if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC)
+ {
+ read_handshake(rec_type, record);
+ }
+ else if(rec_type == HEARTBEAT && m_peer_supports_heartbeats)
+ {
+ Heartbeat_Message heartbeat(record);
+
+ const std::vector<byte>& payload = heartbeat.payload();
+
+ if(heartbeat.is_request() && !state)
+ {
+ Heartbeat_Message response(Heartbeat_Message::RESPONSE,
+ &payload[0], payload.size());
+
+ writer.send(HEARTBEAT, response.contents());
+ }
+ else
+ {
+ // pass up to the application
+ proc_fn(&payload[0], payload.size(), Alert(Alert::HEARTBEAT_PAYLOAD));
+ }
+ }
+ else if(rec_type == APPLICATION_DATA)
+ {
+ if(handshake_completed)
+ {
+ /*
+ * OpenSSL among others sends empty records in versions
+ * before TLS v1.1 in order to randomize the IV of the
+ * following record. Avoid spurious callbacks.
+ */
+ if(record.size() > 0)
+ proc_fn(&record[0], record.size(), Alert());
+ }
+ else
+ {
+ throw Unexpected_Message("Application data before handshake done");
+ }
+ }
+ else if(rec_type == ALERT)
+ {
+ Alert alert_msg(record);
+
+ alert_notify(alert_msg);
+
+ proc_fn(nullptr, 0, alert_msg);
+
+ if(alert_msg.type() == Alert::CLOSE_NOTIFY)
+ {
+ if(connection_closed)
+ reader.reset();
+ else
+ send_alert(Alert(Alert::CLOSE_NOTIFY)); // reply in kind
+ }
+ else if(alert_msg.is_fatal())
+ {
+ // delete state immediately
+ connection_closed = true;
+
+ delete state;
+ state = nullptr;
+
+ writer.reset();
+ reader.reset();
+ }
+ }
+ else
+ throw Unexpected_Message("Unknown TLS message type " +
+ std::to_string(rec_type) + " received");
+ }
+
+ return 0; // on a record boundary
+ }
+ catch(TLS_Exception& e)
+ {
+ send_alert(Alert(e.type(), true));
+ throw;
+ }
+ catch(Decoding_Error& e)
+ {
+ send_alert(Alert(Alert::DECODE_ERROR, true));
+ throw;
+ }
+ catch(Internal_Error& e)
+ {
+ send_alert(Alert(Alert::INTERNAL_ERROR, true));
+ throw;
+ }
+ catch(std::exception& e)
+ {
+ send_alert(Alert(Alert::INTERNAL_ERROR, true));
+ throw;
+ }
+ }
+
+/*
+* Split up and process handshake messages
+*/
+void Channel::read_handshake(byte rec_type,
+ const std::vector<byte>& rec_buf)
+ {
+ if(rec_type == HANDSHAKE)
+ {
+ if(!state)
+ state = new Handshake_State(new Stream_Handshake_Reader);
+ state->handshake_reader()->add_input(&rec_buf[0], rec_buf.size());
+ }
+
+ BOTAN_ASSERT(state, "Handshake message recieved without state in place");
+
+ while(true)
+ {
+ Handshake_Type type = HANDSHAKE_NONE;
+
+ if(rec_type == HANDSHAKE)
+ {
+ if(state->handshake_reader()->have_full_record())
+ {
+ std::pair<Handshake_Type, std::vector<byte> > msg =
+ state->handshake_reader()->get_next_record();
+ process_handshake_msg(msg.first, msg.second);
+ }
+ else
+ break;
+ }
+ else if(rec_type == CHANGE_CIPHER_SPEC)
+ {
+ if(state->handshake_reader()->empty() && rec_buf.size() == 1 && rec_buf[0] == 1)
+ process_handshake_msg(HANDSHAKE_CCS, std::vector<byte>());
+ else
+ throw Decoding_Error("Malformed ChangeCipherSpec message");
+ }
+ else
+ throw Decoding_Error("Unknown message type in handshake processing");
+
+ if(type == HANDSHAKE_CCS || !state || !state->handshake_reader()->have_full_record())
+ break;
+ }
+ }
+
+void Channel::heartbeat(const byte payload[], size_t payload_size)
+ {
+ if(!is_active())
+ throw std::runtime_error("Heartbeat cannot be sent on inactive TLS connection");
+
+ if(m_heartbeat_sending_allowed)
+ {
+ Heartbeat_Message heartbeat(Heartbeat_Message::REQUEST,
+ payload, payload_size);
+
+ writer.send(HEARTBEAT, heartbeat.contents());
+ }
+ }
+
+void Channel::send(const byte buf[], size_t buf_size)
+ {
+ if(!is_active())
+ throw std::runtime_error("Data cannot be sent on inactive TLS connection");
+
+ writer.send(APPLICATION_DATA, buf, buf_size);
+ }
+
+void Channel::send_alert(const Alert& alert)
+ {
+ if(alert.is_valid() && !connection_closed)
+ {
+ try
+ {
+ writer.send_alert(alert);
+ }
+ catch(...) { /* swallow it */ }
+ }
+
+ if(!connection_closed && (alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal()))
+ {
+ connection_closed = true;
+
+ delete state;
+ state = nullptr;
+
+ writer.reset();
+ }
+ }
+
+void Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello)
+ {
+ if(initial_handshake)
+ {
+ secure_renegotiation = client_hello->secure_renegotiation();
+ }
+ else
+ {
+ if(secure_renegotiation != client_hello->secure_renegotiation())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client changed its mind about secure renegotiation");
+ }
+
+ if(client_hello->secure_renegotiation())
+ {
+ const std::vector<byte>& data = client_hello->renegotiation_info();
+
+ if(initial_handshake)
+ {
+ if(!data.empty())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client sent renegotiation data on initial handshake");
+ }
+ else
+ {
+ if(data != for_client_hello())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client sent bad renegotiation data");
+ }
+ }
+ }
+
+void Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
+ {
+ if(initial_handshake)
+ {
+ /* If the client offered but server rejected, then this toggles
+ * secure_renegotiation to off
+ */
+ secure_renegotiation = server_hello->secure_renegotiation();
+ }
+ else
+ {
+ if(secure_renegotiation != server_hello->secure_renegotiation())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server changed its mind about secure renegotiation");
+ }
+
+ if(secure_renegotiation)
+ {
+ const std::vector<byte>& data = server_hello->renegotiation_info();
+
+ if(initial_handshake)
+ {
+ if(!data.empty())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent renegotiation data on initial handshake");
+ }
+ else
+ {
+ if(data != for_server_hello())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent bad renegotiation data");
+ }
+ }
+
+ initial_handshake = false;
+ }
+
+void Channel::Secure_Renegotiation_State::update(Finished* client_finished,
+ Finished* server_finished)
+ {
+ client_verify = client_finished->verify_data();
+ server_verify = server_finished->verify_data();
+ }
+
+}
+
+}
+
diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h
new file mode 100644
index 000000000..fc0595064
--- /dev/null
+++ b/src/tls/tls_channel.h
@@ -0,0 +1,155 @@
+/*
+* TLS Channel
+* (C) 2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_CHANNEL_H__
+#define BOTAN_TLS_CHANNEL_H__
+
+#include <botan/tls_policy.h>
+#include <botan/tls_record.h>
+#include <botan/tls_session.h>
+#include <botan/tls_alert.h>
+#include <botan/x509cert.h>
+#include <vector>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Generic interface for TLS endpoint
+*/
+class BOTAN_DLL Channel
+ {
+ public:
+ /**
+ * Inject TLS traffic received from counterparty
+ * @return a hint as the how many more bytes we need to process the
+ * current record (this may be 0 if on a record boundary)
+ */
+ virtual size_t received_data(const byte buf[], size_t buf_size);
+
+ /**
+ * Inject plaintext intended for counterparty
+ */
+ virtual void send(const byte buf[], size_t buf_size);
+
+ /**
+ * Send a close notification alert
+ */
+ void close() { send_alert(Alert(Alert::CLOSE_NOTIFY)); }
+
+ /**
+ * @return true iff the connection is active for sending application data
+ */
+ bool is_active() const { return handshake_completed && !is_closed(); }
+
+ /**
+ * @return true iff the connection has been definitely closed
+ */
+ bool is_closed() const { return connection_closed; }
+
+ /**
+ * Attempt to renegotiate the session
+ * @param force_full_renegotiation if true, require a full renegotiation,
+ * otherwise allow session resumption
+ */
+ virtual void renegotiate(bool force_full_renegotiation) = 0;
+
+ /**
+ * Attempt to send a heartbeat message (if negotiated with counterparty)
+ * @param payload will be echoed back
+ * @param countents_size size of payload in bytes
+ */
+ void heartbeat(const byte payload[], size_t payload_size);
+
+ /**
+ * Attempt to send a heartbeat message (if negotiated with counterparty)
+ */
+ void heartbeat() { heartbeat(nullptr, 0); }
+
+ /**
+ * @return certificate chain of the peer (may be empty)
+ */
+ std::vector<X509_Certificate> peer_cert_chain() const { return peer_certs; }
+
+ Channel(std::function<void (const byte[], size_t)> socket_output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_complete);
+
+ virtual ~Channel();
+ protected:
+
+ /**
+ * Send a TLS alert message. If the alert is fatal, the
+ * internal state (keys, etc) will be reset
+ * @param level is warning or fatal
+ * @param type is the type of alert
+ */
+ void send_alert(const Alert& alert);
+
+ virtual void read_handshake(byte rec_type,
+ const std::vector<byte>& rec_buf);
+
+ virtual void process_handshake_msg(Handshake_Type type,
+ const std::vector<byte>& contents) = 0;
+
+ virtual void alert_notify(const Alert& alert) = 0;
+
+ std::function<void (const byte[], size_t, Alert)> proc_fn;
+ std::function<bool (const Session&)> handshake_fn;
+
+ Record_Writer writer;
+ Record_Reader reader;
+
+ std::vector<X509_Certificate> peer_certs;
+
+ class Handshake_State* state;
+
+ class Secure_Renegotiation_State
+ {
+ public:
+ Secure_Renegotiation_State() : initial_handshake(true),
+ secure_renegotiation(false)
+ {}
+
+ void update(class Client_Hello* client_hello);
+ void update(class Server_Hello* server_hello);
+
+ void update(class Finished* client_finished,
+ class Finished* server_finished);
+
+ const std::vector<byte>& for_client_hello() const
+ { return client_verify; }
+
+ std::vector<byte> for_server_hello() const
+ {
+ std::vector<byte> buf = client_verify;
+ buf += server_verify;
+ return buf;
+ }
+
+ bool supported() const { return secure_renegotiation; }
+ bool renegotiation() const { return !initial_handshake; }
+ private:
+ bool initial_handshake;
+ bool secure_renegotiation;
+ std::vector<byte> client_verify, server_verify;
+ };
+
+ Secure_Renegotiation_State secure_renegotiation;
+
+ bool handshake_completed;
+ bool connection_closed;
+ bool m_peer_supports_heartbeats;
+ bool m_heartbeat_sending_allowed;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_ciphersuite.cpp b/src/tls/tls_ciphersuite.cpp
new file mode 100644
index 000000000..e3bda06e4
--- /dev/null
+++ b/src/tls/tls_ciphersuite.cpp
@@ -0,0 +1,104 @@
+/*
+* TLS Cipher Suite
+* (C) 2004-2010,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_ciphersuite.h>
+#include <botan/parsing.h>
+#include <sstream>
+#include <stdexcept>
+
+namespace Botan {
+
+namespace TLS {
+
+Ciphersuite Ciphersuite::by_name(const std::string& name)
+ {
+ for(size_t i = 0; i != 65536; ++i)
+ {
+ Ciphersuite suite = Ciphersuite::by_id(i);
+
+ if(!suite.valid())
+ continue; // not a ciphersuite we know, skip
+
+ if(suite.to_string() == name)
+ return suite;
+ }
+
+ return Ciphersuite(); // some unknown ciphersuite
+ }
+
+bool Ciphersuite::psk_ciphersuite() const
+ {
+ return (kex_algo() == "PSK" ||
+ kex_algo() == "DHE_PSK" ||
+ kex_algo() == "ECDHE_PSK");
+ }
+
+bool Ciphersuite::ecc_ciphersuite() const
+ {
+ return (kex_algo() == "ECDH" || sig_algo() == "ECDSA");
+ }
+
+std::string Ciphersuite::to_string() const
+ {
+ if(m_cipher_keylen == 0)
+ throw std::runtime_error("Ciphersuite::to_string - no value set");
+
+ std::ostringstream out;
+
+ out << "TLS_";
+
+ if(kex_algo() != "RSA")
+ {
+ if(kex_algo() == "DH")
+ out << "DHE";
+ else if(kex_algo() == "ECDH")
+ out << "ECDHE";
+ else
+ out << kex_algo();
+
+ out << '_';
+ }
+
+ if(sig_algo() == "DSA")
+ out << "DSS_";
+ else if(sig_algo() != "")
+ out << sig_algo() << '_';
+
+ out << "WITH_";
+
+ if(cipher_algo() == "ARC4")
+ {
+ out << "RC4_128_";
+ }
+ else
+ {
+ if(cipher_algo() == "3DES")
+ out << "3DES_EDE";
+ else if(cipher_algo() == "Camellia")
+ out << "CAMELLIA_" << std::to_string(8*cipher_keylen());
+ else
+ out << replace_char(cipher_algo(), '-', '_');
+
+ out << "_CBC_";
+ }
+
+ if(mac_algo() == "SHA-1")
+ out << "SHA";
+ else if(mac_algo() == "SHA-256")
+ out << "SHA256";
+ else if(mac_algo() == "SHA-384")
+ out << "SHA384";
+ else
+ out << mac_algo();
+
+ return out.str();
+ }
+
+}
+
+}
+
diff --git a/src/tls/tls_ciphersuite.h b/src/tls/tls_ciphersuite.h
new file mode 100644
index 000000000..dcb4b6a6f
--- /dev/null
+++ b/src/tls/tls_ciphersuite.h
@@ -0,0 +1,73 @@
+/*
+* TLS Cipher Suites
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_CIPHER_SUITES_H__
+#define BOTAN_TLS_CIPHER_SUITES_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Ciphersuite Information
+*/
+class BOTAN_DLL Ciphersuite
+ {
+ public:
+ /**
+ * Convert an SSL/TLS ciphersuite to algorithm fields
+ */
+ static Ciphersuite by_id(u16bit suite);
+
+ static Ciphersuite by_name(const std::string& name);
+
+ /**
+ * Formats the ciphersuite back to an RFC-style ciphersuite string
+ */
+ std::string to_string() const;
+
+ bool psk_ciphersuite() const;
+ bool ecc_ciphersuite() const;
+
+ std::string kex_algo() const { return m_kex_algo; }
+ std::string sig_algo() const { return m_sig_algo; }
+
+ std::string cipher_algo() const { return m_cipher_algo; }
+ std::string mac_algo() const { return m_mac_algo; }
+
+ size_t cipher_keylen() const { return m_cipher_keylen; }
+
+ bool valid() const { return (m_cipher_keylen > 0); }
+
+ Ciphersuite() : m_cipher_keylen(0) {}
+
+ Ciphersuite(const std::string& sig_algo,
+ const std::string& kex_algo,
+ const std::string& mac_algo,
+ const std::string& cipher_algo,
+ size_t cipher_algo_keylen) :
+ m_sig_algo(sig_algo),
+ m_kex_algo(kex_algo),
+ m_mac_algo(mac_algo),
+ m_cipher_algo(cipher_algo),
+ m_cipher_keylen(cipher_algo_keylen)
+ {
+ }
+
+ private:
+ std::string m_sig_algo, m_kex_algo, m_mac_algo, m_cipher_algo;
+ size_t m_cipher_keylen;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
new file mode 100644
index 000000000..1ca256f3e
--- /dev/null
+++ b/src/tls/tls_client.cpp
@@ -0,0 +1,486 @@
+/*
+* TLS Client
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_client.h>
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/stl_util.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+/*
+* TLS Client Constructor
+*/
+Client::Client(std::function<void (const byte[], size_t)> output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_fn,
+ Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::string& hostname,
+ std::function<std::string (std::vector<std::string>)> next_protocol) :
+ Channel(output_fn, proc_fn, handshake_fn),
+ policy(policy),
+ rng(rng),
+ session_manager(session_manager),
+ creds(creds),
+ m_hostname(hostname)
+ {
+ writer.set_version(Protocol_Version::SSL_V3);
+
+ state = new Handshake_State(new Stream_Handshake_Reader);
+ state->set_expected_next(SERVER_HELLO);
+
+ state->client_npn_cb = next_protocol;
+
+ const std::string srp_identifier = creds.srp_identifier("tls-client", hostname);
+
+ const bool send_npn_request = static_cast<bool>(next_protocol);
+
+ if(hostname != "")
+ {
+ Session session_info;
+ if(session_manager.load_from_host_info(hostname, 0, session_info))
+ {
+ if(session_info.srp_identifier() == srp_identifier)
+ {
+ state->client_hello = new Client_Hello(
+ writer,
+ state->hash,
+ policy,
+ rng,
+ secure_renegotiation.for_client_hello(),
+ session_info,
+ send_npn_request);
+
+ state->resume_master_secret = session_info.master_secret();
+ }
+ }
+ }
+
+ if(!state->client_hello) // not resuming
+ {
+ state->client_hello = new Client_Hello(
+ writer,
+ state->hash,
+ policy,
+ rng,
+ secure_renegotiation.for_client_hello(),
+ send_npn_request,
+ hostname,
+ srp_identifier);
+ }
+
+ secure_renegotiation.update(state->client_hello);
+ }
+
+/*
+* Send a new client hello to renegotiate
+*/
+void Client::renegotiate(bool force_full_renegotiation)
+ {
+ if(state && state->client_hello)
+ return; // currently in active handshake
+
+ delete state;
+ state = new Handshake_State(new Stream_Handshake_Reader);
+
+ state->set_expected_next(SERVER_HELLO);
+
+ if(!force_full_renegotiation)
+ {
+ Session session_info;
+ if(session_manager.load_from_host_info(m_hostname, 0, session_info))
+ {
+ state->client_hello = new Client_Hello(
+ writer,
+ state->hash,
+ policy,
+ rng,
+ secure_renegotiation.for_client_hello(),
+ session_info);
+
+ state->resume_master_secret = session_info.master_secret();
+ }
+ }
+
+ if(!state->client_hello)
+ {
+ state->client_hello = new Client_Hello(
+ writer,
+ state->hash,
+ policy,
+ rng,
+ secure_renegotiation.for_client_hello());
+ }
+
+ secure_renegotiation.update(state->client_hello);
+ }
+
+void Client::alert_notify(const Alert& alert)
+ {
+ if(alert.type() == Alert::NO_RENEGOTIATION)
+ {
+ if(handshake_completed && state)
+ {
+ delete state;
+ state = nullptr;
+ }
+ }
+ }
+
+/*
+* Process a handshake message
+*/
+void Client::process_handshake_msg(Handshake_Type type,
+ const std::vector<byte>& contents)
+ {
+ if(!state)
+ throw Unexpected_Message("Unexpected handshake message from server");
+
+ if(type == HELLO_REQUEST)
+ {
+ Hello_Request hello_request(contents);
+
+ // Ignore request entirely if we are currently negotiating a handshake
+ if(state->client_hello)
+ return;
+
+ if(!secure_renegotiation.supported() && policy.require_secure_renegotiation())
+ {
+ delete state;
+ state = nullptr;
+
+ // RFC 5746 section 4.2
+ send_alert(Alert(Alert::NO_RENEGOTIATION));
+ return;
+ }
+
+ renegotiate(false);
+
+ return;
+ }
+
+ state->confirm_transition_to(type);
+
+ if(type != HANDSHAKE_CCS && type != FINISHED)
+ state->hash.update(type, contents);
+
+ if(type == SERVER_HELLO)
+ {
+ state->server_hello = new Server_Hello(contents);
+
+ if(!state->client_hello->offered_suite(state->server_hello->ciphersuite()))
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server replied with ciphersuite we didn't send");
+ }
+
+ if(!value_exists(state->client_hello->compression_methods(),
+ state->server_hello->compression_method()))
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server replied with compression method we didn't send");
+ }
+
+ if(!state->client_hello->next_protocol_notification() &&
+ state->server_hello->next_protocol_notification())
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent next protocol but we didn't request it");
+ }
+
+ if(state->server_hello->supports_session_ticket())
+ {
+ if(!state->client_hello->supports_session_ticket())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent session ticket extension but we did not");
+ }
+
+ state->set_version(state->server_hello->version());
+
+ writer.set_version(state->version());
+ reader.set_version(state->version());
+
+ secure_renegotiation.update(state->server_hello);
+
+ m_peer_supports_heartbeats = state->server_hello->supports_heartbeats();
+ m_heartbeat_sending_allowed = state->server_hello->peer_can_send_heartbeats();
+
+ state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());
+
+ const bool server_returned_same_session_id =
+ !state->server_hello->session_id().empty() &&
+ (state->server_hello->session_id() == state->client_hello->session_id());
+
+ if(server_returned_same_session_id)
+ {
+ // successful resumption
+
+ /*
+ * In this case, we offered the version used in the original
+ * session, and the server must resume with the same version.
+ */
+ if(state->server_hello->version() != state->client_hello->version())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server resumed session but with wrong version");
+
+ state->keys = Session_Keys(state,
+ state->resume_master_secret,
+ true);
+
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else
+ {
+ // new session
+
+ if(state->version() > state->client_hello->version())
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client: Server replied with bad version");
+ }
+
+ if(state->version() < policy.min_version())
+ {
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Client: Server is too old for specified policy");
+ }
+
+ if(state->suite.sig_algo() != "")
+ {
+ state->set_expected_next(CERTIFICATE);
+ }
+ else if(state->suite.kex_algo() == "PSK")
+ {
+ /* PSK is anonymous so no certificate/cert req message is
+ ever sent. The server may or may not send a server kex,
+ depending on if it has an identity hint for us.
+
+ (EC)DHE_PSK always sends a server key exchange for the
+ DH exchange portion.
+ */
+
+ state->set_expected_next(SERVER_KEX);
+ state->set_expected_next(SERVER_HELLO_DONE);
+ }
+ else if(state->suite.kex_algo() != "RSA")
+ {
+ state->set_expected_next(SERVER_KEX);
+ }
+ else
+ {
+ state->set_expected_next(CERTIFICATE_REQUEST); // optional
+ state->set_expected_next(SERVER_HELLO_DONE);
+ }
+ }
+ }
+ else if(type == CERTIFICATE)
+ {
+ if(state->suite.kex_algo() != "RSA")
+ {
+ state->set_expected_next(SERVER_KEX);
+ }
+ else
+ {
+ state->set_expected_next(CERTIFICATE_REQUEST); // optional
+ state->set_expected_next(SERVER_HELLO_DONE);
+ }
+
+ state->server_certs = new Certificate(contents);
+
+ peer_certs = state->server_certs->cert_chain();
+ if(peer_certs.size() == 0)
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client: No certificates sent by server");
+
+ try
+ {
+ creds.verify_certificate_chain("tls-client", m_hostname, peer_certs);
+ }
+ catch(std::exception& e)
+ {
+ throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
+ }
+
+ std::unique_ptr<Public_Key> peer_key(peer_certs[0].subject_public_key());
+
+ if(peer_key->algo_name() != state->suite.sig_algo())
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Certificate key type did not match ciphersuite");
+ }
+ else if(type == SERVER_KEX)
+ {
+ state->set_expected_next(CERTIFICATE_REQUEST); // optional
+ state->set_expected_next(SERVER_HELLO_DONE);
+
+ state->server_kex = new Server_Key_Exchange(contents,
+ state->suite.kex_algo(),
+ state->suite.sig_algo(),
+ state->version());
+
+ if(state->suite.sig_algo() != "")
+ {
+ if(!state->server_kex->verify(peer_certs[0], state))
+ {
+ throw TLS_Exception(Alert::DECRYPT_ERROR,
+ "Bad signature on server key exchange");
+ }
+ }
+ }
+ else if(type == CERTIFICATE_REQUEST)
+ {
+ state->set_expected_next(SERVER_HELLO_DONE);
+ state->cert_req = new Certificate_Req(contents, state->version());
+ }
+ else if(type == SERVER_HELLO_DONE)
+ {
+ state->server_hello_done = new Server_Hello_Done(contents);
+
+ if(state->received_handshake_msg(CERTIFICATE_REQUEST))
+ {
+ const std::vector<std::string>& types =
+ state->cert_req->acceptable_cert_types();
+
+ std::vector<X509_Certificate> client_certs =
+ creds.cert_chain(types,
+ "tls-client",
+ m_hostname);
+
+ state->client_certs = new Certificate(writer,
+ state->hash,
+ client_certs);
+ }
+
+ state->client_kex =
+ new Client_Key_Exchange(writer,
+ state,
+ creds,
+ peer_certs,
+ m_hostname,
+ rng);
+
+ state->keys = Session_Keys(state,
+ state->client_kex->pre_master_secret(),
+ false);
+
+ if(state->received_handshake_msg(CERTIFICATE_REQUEST) &&
+ !state->client_certs->empty())
+ {
+ Private_Key* private_key =
+ creds.private_key_for(state->client_certs->cert_chain()[0],
+ "tls-client",
+ m_hostname);
+
+ state->client_verify = new Certificate_Verify(writer,
+ state,
+ rng,
+ private_key);
+ }
+
+ writer.send(CHANGE_CIPHER_SPEC, 1);
+
+ writer.activate(CLIENT, state->suite, state->keys,
+ state->server_hello->compression_method());
+
+ if(state->server_hello->next_protocol_notification())
+ {
+ const std::string protocol =
+ state->client_npn_cb(state->server_hello->next_protocols());
+
+ state->next_protocol = new Next_Protocol(writer, state->hash, protocol);
+ }
+
+ state->client_finished = new Finished(writer, state, CLIENT);
+
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else if(type == NEW_SESSION_TICKET)
+ {
+ state->new_session_ticket = new New_Session_Ticket(contents);
+
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else if(type == HANDSHAKE_CCS)
+ {
+ state->set_expected_next(FINISHED);
+
+ reader.activate(CLIENT, state->suite, state->keys,
+ state->server_hello->compression_method());
+ }
+ else if(type == FINISHED)
+ {
+ state->set_expected_next(HELLO_REQUEST);
+
+ state->server_finished = new Finished(contents);
+
+ if(!state->server_finished->verify(state, SERVER))
+ throw TLS_Exception(Alert::DECRYPT_ERROR,
+ "Finished message didn't verify");
+
+ state->hash.update(type, contents);
+
+ if(!state->client_finished) // session resume case
+ {
+ writer.send(CHANGE_CIPHER_SPEC, 1);
+
+ writer.activate(CLIENT, state->suite, state->keys,
+ state->server_hello->compression_method());
+
+ state->client_finished = new Finished(writer, state, CLIENT);
+ }
+
+ secure_renegotiation.update(state->client_finished, state->server_finished);
+
+ std::vector<byte> session_id = state->server_hello->session_id();
+
+ const std::vector<byte>& session_ticket = state->session_ticket();
+
+ if(session_id.empty() && !session_ticket.empty())
+ session_id = make_hello_random(rng);
+
+ Session session_info(
+ session_id,
+ state->keys.master_secret(),
+ state->server_hello->version(),
+ state->server_hello->ciphersuite(),
+ state->server_hello->compression_method(),
+ CLIENT,
+ secure_renegotiation.supported(),
+ state->server_hello->fragment_size(),
+ peer_certs,
+ session_ticket,
+ m_hostname,
+ ""
+ );
+
+ if(handshake_fn(session_info))
+ session_manager.save(session_info);
+ else
+ session_manager.remove_entry(session_info.session_id());
+
+ delete state;
+ state = nullptr;
+ handshake_completed = true;
+ }
+ else
+ throw Unexpected_Message("Unknown handshake message received");
+ }
+
+}
+
+}
diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h
new file mode 100644
index 000000000..2844780bd
--- /dev/null
+++ b/src/tls/tls_client.h
@@ -0,0 +1,74 @@
+/*
+* TLS Client
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_CLIENT_H__
+#define BOTAN_TLS_CLIENT_H__
+
+#include <botan/tls_channel.h>
+#include <botan/tls_session_manager.h>
+#include <botan/credentials_manager.h>
+#include <vector>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* SSL/TLS Client
+*/
+class BOTAN_DLL Client : public Channel
+ {
+ public:
+ /**
+ * Set up a new TLS client session
+ * @param socket_output_fn is called with data for the outbound socket
+ * @param proc_fn is called when new data (application or alerts) is received
+ * @param handshake_complete is called when a handshake is completed
+ * @param session_manager manages session state
+ * @param creds manages application/user credentials
+ * @param policy specifies other connection policy information
+ * @param rng a random number generator
+ * @param servername the server's DNS name, if known
+ * @param next_protocol allows the client to specify what the next
+ * protocol will be. For more information read
+ * http://technotes.googlecode.com/git/nextprotoneg.html.
+ *
+ * If the function is not empty, NPN will be negotiated
+ * and if the server supports NPN the function will be
+ * called with the list of protocols the server advertised;
+ * the client should return the protocol it would like to use.
+ */
+ Client(std::function<void (const byte[], size_t)> socket_output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_complete,
+ Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::string& servername = "",
+ std::function<std::string (std::vector<std::string>)> next_protocol =
+ std::function<std::string (std::vector<std::string>)>());
+
+ void renegotiate(bool force_full_renegotiation);
+ private:
+ void process_handshake_msg(Handshake_Type type,
+ const std::vector<byte>& contents) override;
+
+ void alert_notify(const Alert& alert);
+
+ const Policy& policy;
+ RandomNumberGenerator& rng;
+ Session_Manager& session_manager;
+ Credentials_Manager& creds;
+ const std::string m_hostname;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/ssl/tls_exceptn.h b/src/tls/tls_exceptn.h
index 37b9c0d27..ad19c6c9d 100644
--- a/src/ssl/tls_exceptn.h
+++ b/src/tls/tls_exceptn.h
@@ -9,24 +9,26 @@
#define BOTAN_TLS_EXCEPTION_H__
#include <botan/exceptn.h>
-#include <botan/tls_magic.h>
+#include <botan/tls_alert.h>
namespace Botan {
+namespace TLS {
+
/**
* Exception Base Class
*/
class BOTAN_DLL TLS_Exception : public Exception
{
public:
- Alert_Type type() const throw() { return alert_type; }
+ Alert::Type type() const throw() { return alert_type; }
- TLS_Exception(Alert_Type type,
+ TLS_Exception(Alert::Type type,
const std::string& err_msg = "Unknown error") :
Exception(err_msg), alert_type(type) {}
private:
- Alert_Type alert_type;
+ Alert::Type alert_type;
};
/**
@@ -35,9 +37,11 @@ class BOTAN_DLL TLS_Exception : public Exception
struct BOTAN_DLL Unexpected_Message : public TLS_Exception
{
Unexpected_Message(const std::string& err) :
- TLS_Exception(UNEXPECTED_MESSAGE, err) {}
+ TLS_Exception(Alert::UNEXPECTED_MESSAGE, err) {}
};
}
+}
+
#endif
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
new file mode 100644
index 000000000..df25c40a5
--- /dev/null
+++ b/src/tls/tls_extensions.cpp
@@ -0,0 +1,524 @@
+/*
+* TLS Extensions
+* (C) 2011,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/tls_exceptn.h>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+Extension* make_extension(TLS_Data_Reader& reader,
+ u16bit code,
+ u16bit size)
+ {
+ switch(code)
+ {
+ case TLSEXT_SERVER_NAME_INDICATION:
+ return new Server_Name_Indicator(reader, size);
+
+ case TLSEXT_MAX_FRAGMENT_LENGTH:
+ return new Maximum_Fragment_Length(reader, size);
+
+ case TLSEXT_SRP_IDENTIFIER:
+ return new SRP_Identifier(reader, size);
+
+ case TLSEXT_USABLE_ELLIPTIC_CURVES:
+ return new Supported_Elliptic_Curves(reader, size);
+
+ case TLSEXT_SAFE_RENEGOTIATION:
+ return new Renegotation_Extension(reader, size);
+
+ case TLSEXT_SIGNATURE_ALGORITHMS:
+ return new Signature_Algorithms(reader, size);
+
+ case TLSEXT_NEXT_PROTOCOL:
+ return new Next_Protocol_Notification(reader, size);
+
+ case TLSEXT_HEARTBEAT_SUPPORT:
+ return new Heartbeat_Support_Indicator(reader, size);
+
+ case TLSEXT_SESSION_TICKET:
+ return new Session_Ticket(reader, size);
+
+ default:
+ return nullptr; // not known
+ }
+ }
+
+}
+
+Extensions::Extensions(TLS_Data_Reader& reader)
+ {
+ if(reader.has_remaining())
+ {
+ const u16bit all_extn_size = reader.get_u16bit();
+
+ if(reader.remaining_bytes() != all_extn_size)
+ throw Decoding_Error("Bad extension size");
+
+ while(reader.has_remaining())
+ {
+ const u16bit extension_code = reader.get_u16bit();
+ const u16bit extension_size = reader.get_u16bit();
+
+ Extension* extn = make_extension(reader,
+ extension_code,
+ extension_size);
+
+ if(extn)
+ this->add(extn);
+ else // unknown/unhandled extension
+ reader.discard_next(extension_size);
+ }
+ }
+ }
+
+std::vector<byte> Extensions::serialize() const
+ {
+ std::vector<byte> buf(2); // 2 bytes for length field
+
+ for(std::map<Handshake_Extension_Type, Extension*>::const_iterator i = extensions.begin();
+ i != extensions.end(); ++i)
+ {
+ if(i->second->empty())
+ continue;
+
+ const u16bit extn_code = i->second->type();
+
+ std::vector<byte> extn_val = i->second->serialize();
+
+ buf.push_back(get_byte(0, extn_code));
+ buf.push_back(get_byte(1, extn_code));
+
+ buf.push_back(get_byte<u16bit>(0, extn_val.size()));
+ buf.push_back(get_byte<u16bit>(1, extn_val.size()));
+
+ buf += extn_val;
+ }
+
+ const u16bit extn_size = buf.size() - 2;
+
+ buf[0] = get_byte(0, extn_size);
+ buf[1] = get_byte(1, extn_size);
+
+ // avoid sending a completely empty extensions block
+ if(buf.size() == 2)
+ return std::vector<byte>();
+
+ return buf;
+ }
+
+Extensions::~Extensions()
+ {
+ for(std::map<Handshake_Extension_Type, Extension*>::const_iterator i = extensions.begin();
+ i != extensions.end(); ++i)
+ {
+ delete i->second;
+ }
+
+ extensions.clear();
+ }
+
+Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ /*
+ * This is used by the server to confirm that it knew the name
+ */
+ if(extension_size == 0)
+ return;
+
+ u16bit name_bytes = reader.get_u16bit();
+
+ if(name_bytes + 2 != extension_size)
+ throw Decoding_Error("Bad encoding of SNI extension");
+
+ while(name_bytes)
+ {
+ byte name_type = reader.get_byte();
+ name_bytes--;
+
+ if(name_type == 0) // DNS
+ {
+ sni_host_name = reader.get_string(2, 1, 65535);
+ name_bytes -= (2 + sni_host_name.size());
+ }
+ else // some other unknown name type
+ {
+ reader.discard_next(name_bytes);
+ name_bytes = 0;
+ }
+ }
+ }
+
+std::vector<byte> Server_Name_Indicator::serialize() const
+ {
+ std::vector<byte> buf;
+
+ size_t name_len = sni_host_name.size();
+
+ buf.push_back(get_byte<u16bit>(0, name_len+3));
+ buf.push_back(get_byte<u16bit>(1, name_len+3));
+ buf.push_back(0); // DNS
+
+ buf.push_back(get_byte<u16bit>(0, name_len));
+ buf.push_back(get_byte<u16bit>(1, name_len));
+
+ buf += std::make_pair(
+ reinterpret_cast<const byte*>(sni_host_name.data()),
+ sni_host_name.size());
+
+ return buf;
+ }
+
+SRP_Identifier::SRP_Identifier(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ srp_identifier = reader.get_string(1, 1, 255);
+
+ if(srp_identifier.size() + 1 != extension_size)
+ throw Decoding_Error("Bad encoding for SRP identifier extension");
+ }
+
+std::vector<byte> SRP_Identifier::serialize() const
+ {
+ std::vector<byte> buf;
+
+ const byte* srp_bytes =
+ reinterpret_cast<const byte*>(srp_identifier.data());
+
+ append_tls_length_value(buf, srp_bytes, srp_identifier.size(), 1);
+
+ return buf;
+ }
+
+Renegotation_Extension::Renegotation_Extension(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ reneg_data = reader.get_range<byte>(1, 0, 255);
+
+ if(reneg_data.size() + 1 != extension_size)
+ throw Decoding_Error("Bad encoding for secure renegotiation extn");
+ }
+
+std::vector<byte> Renegotation_Extension::serialize() const
+ {
+ std::vector<byte> buf;
+ append_tls_length_value(buf, reneg_data, 1);
+ return buf;
+ }
+
+size_t Maximum_Fragment_Length::fragment_size() const
+ {
+ switch(val)
+ {
+ case 1:
+ return 512;
+ case 2:
+ return 1024;
+ case 3:
+ return 2048;
+ case 4:
+ return 4096;
+ default:
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Bad value in maximum fragment extension");
+ }
+ }
+
+Maximum_Fragment_Length::Maximum_Fragment_Length(size_t max_fragment)
+ {
+ if(max_fragment == 512)
+ val = 1;
+ else if(max_fragment == 1024)
+ val = 2;
+ else if(max_fragment == 2048)
+ val = 3;
+ else if(max_fragment == 4096)
+ val = 4;
+ else
+ throw std::invalid_argument("Bad setting " +
+ std::to_string(max_fragment) +
+ " for maximum fragment size");
+ }
+
+Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ if(extension_size != 1)
+ throw Decoding_Error("Bad size for maximum fragment extension");
+ val = reader.get_byte();
+ }
+
+Next_Protocol_Notification::Next_Protocol_Notification(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ if(extension_size == 0)
+ return; // empty extension
+
+ size_t bytes_remaining = extension_size;
+
+ while(bytes_remaining)
+ {
+ const std::string p = reader.get_string(1, 0, 255);
+
+ if(bytes_remaining < p.size() + 1)
+ throw Decoding_Error("Bad encoding for next protocol extension");
+
+ bytes_remaining -= (p.size() + 1);
+
+ m_protocols.push_back(p);
+ }
+ }
+
+std::vector<byte> Next_Protocol_Notification::serialize() const
+ {
+ std::vector<byte> buf;
+
+ for(size_t i = 0; i != m_protocols.size(); ++i)
+ {
+ const std::string p = m_protocols[i];
+
+ if(p != "")
+ append_tls_length_value(buf,
+ reinterpret_cast<const byte*>(p.data()),
+ p.size(),
+ 1);
+ }
+
+ return buf;
+ }
+
+std::string Supported_Elliptic_Curves::curve_id_to_name(u16bit id)
+ {
+ switch(id)
+ {
+ case 15:
+ return "secp160k1";
+ case 16:
+ return "secp160r1";
+ case 17:
+ return "secp160r2";
+ case 18:
+ return "secp192k1";
+ case 19:
+ return "secp192r1";
+ case 20:
+ return "secp224k1";
+ case 21:
+ return "secp224r1";
+ case 22:
+ return "secp256k1";
+ case 23:
+ return "secp256r1";
+ case 24:
+ return "secp384r1";
+ case 25:
+ return "secp521r1";
+ default:
+ return ""; // something we don't know or support
+ }
+ }
+
+u16bit Supported_Elliptic_Curves::name_to_curve_id(const std::string& name)
+ {
+ if(name == "secp160k1")
+ return 15;
+ if(name == "secp160r1")
+ return 16;
+ if(name == "secp160r2")
+ return 17;
+ if(name == "secp192k1")
+ return 18;
+ if(name == "secp192r1")
+ return 19;
+ if(name == "secp224k1")
+ return 20;
+ if(name == "secp224r1")
+ return 21;
+ if(name == "secp256k1")
+ return 22;
+ if(name == "secp256r1")
+ return 23;
+ if(name == "secp384r1")
+ return 24;
+ if(name == "secp521r1")
+ return 25;
+
+ throw Invalid_Argument("name_to_curve_id unknown name " + name);
+ }
+
+std::vector<byte> Supported_Elliptic_Curves::serialize() const
+ {
+ std::vector<byte> buf(2);
+
+ for(size_t i = 0; i != m_curves.size(); ++i)
+ {
+ const u16bit id = name_to_curve_id(m_curves[i]);
+ buf.push_back(get_byte(0, id));
+ buf.push_back(get_byte(1, id));
+ }
+
+ buf[0] = get_byte<u16bit>(0, buf.size()-2);
+ buf[1] = get_byte<u16bit>(1, buf.size()-2);
+
+ return buf;
+ }
+
+Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ u16bit len = reader.get_u16bit();
+
+ if(len + 2 != extension_size)
+ throw Decoding_Error("Inconsistent length field in elliptic curve list");
+
+ if(len % 2 == 1)
+ throw Decoding_Error("Elliptic curve list of strange size");
+
+ len /= 2;
+
+ for(size_t i = 0; i != len; ++i)
+ {
+ const u16bit id = reader.get_u16bit();
+ const std::string name = curve_id_to_name(id);
+
+ if(name != "")
+ m_curves.push_back(name);
+ }
+ }
+
+std::string Signature_Algorithms::hash_algo_name(byte code)
+ {
+ switch(code)
+ {
+ // code 1 is MD5 - ignore it
+
+ case 2:
+ return "SHA-1";
+ case 3:
+ return "SHA-224";
+ case 4:
+ return "SHA-256";
+ case 5:
+ return "SHA-384";
+ case 6:
+ return "SHA-512";
+ default:
+ return "";
+ }
+ }
+
+byte Signature_Algorithms::hash_algo_code(const std::string& name)
+ {
+ if(name == "SHA-1")
+ return 2;
+
+ if(name == "SHA-224")
+ return 3;
+
+ if(name == "SHA-256")
+ return 4;
+
+ if(name == "SHA-384")
+ return 5;
+
+ if(name == "SHA-512")
+ return 6;
+
+ throw Internal_Error("Unknown hash ID " + name + " for signature_algorithms");
+ }
+
+std::string Signature_Algorithms::sig_algo_name(byte code)
+ {
+ switch(code)
+ {
+ case 1:
+ return "RSA";
+ case 2:
+ return "DSA";
+ case 3:
+ return "ECDSA";
+ default:
+ return "";
+ }
+ }
+
+byte Signature_Algorithms::sig_algo_code(const std::string& name)
+ {
+ if(name == "RSA")
+ return 1;
+
+ if(name == "DSA")
+ return 2;
+
+ if(name == "ECDSA")
+ return 3;
+
+ throw Internal_Error("Unknown sig ID " + name + " for signature_algorithms");
+ }
+
+std::vector<byte> Signature_Algorithms::serialize() const
+ {
+ std::vector<byte> buf(2);
+
+ for(size_t i = 0; i != m_supported_algos.size(); ++i)
+ {
+ try
+ {
+ const byte hash_code = hash_algo_code(m_supported_algos[i].first);
+ const byte sig_code = sig_algo_code(m_supported_algos[i].second);
+
+ buf.push_back(hash_code);
+ buf.push_back(sig_code);
+ }
+ catch(...)
+ {}
+ }
+
+ buf[0] = get_byte<u16bit>(0, buf.size()-2);
+ buf[1] = get_byte<u16bit>(1, buf.size()-2);
+
+ return buf;
+ }
+
+Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ u16bit len = reader.get_u16bit();
+
+ if(len + 2 != extension_size)
+ throw Decoding_Error("Bad encoding on signature algorithms extension");
+
+ while(len)
+ {
+ const std::string hash_code = hash_algo_name(reader.get_byte());
+ const std::string sig_code = sig_algo_name(reader.get_byte());
+
+ len -= 2;
+
+ // If not something we know, ignore it completely
+ if(hash_code == "" || sig_code == "")
+ continue;
+
+ m_supported_algos.push_back(std::make_pair(hash_code, sig_code));
+ }
+ }
+
+Session_Ticket::Session_Ticket(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ m_ticket = reader.get_elem<byte, std::vector<byte> >(extension_size);
+ }
+
+}
+
+}
diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h
new file mode 100644
index 000000000..542ac0a82
--- /dev/null
+++ b/src/tls/tls_extensions.h
@@ -0,0 +1,381 @@
+/*
+* TLS Extensions
+* (C) 2011-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_EXTENSIONS_H__
+#define BOTAN_TLS_EXTENSIONS_H__
+
+#include <botan/secmem.h>
+#include <botan/tls_magic.h>
+#include <vector>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+namespace TLS {
+
+class TLS_Data_Reader;
+
+enum Handshake_Extension_Type {
+ TLSEXT_SERVER_NAME_INDICATION = 0,
+ TLSEXT_MAX_FRAGMENT_LENGTH = 1,
+ TLSEXT_CLIENT_CERT_URL = 2,
+ TLSEXT_TRUSTED_CA_KEYS = 3,
+ TLSEXT_TRUNCATED_HMAC = 4,
+
+ TLSEXT_CERTIFICATE_TYPES = 9,
+ TLSEXT_USABLE_ELLIPTIC_CURVES = 10,
+ TLSEXT_EC_POINT_FORMATS = 11,
+ TLSEXT_SRP_IDENTIFIER = 12,
+ TLSEXT_SIGNATURE_ALGORITHMS = 13,
+ TLSEXT_HEARTBEAT_SUPPORT = 15,
+
+ TLSEXT_SESSION_TICKET = 35,
+
+ TLSEXT_NEXT_PROTOCOL = 13172,
+
+ TLSEXT_SAFE_RENEGOTIATION = 65281,
+};
+
+/**
+* Base class representing a TLS extension of some kind
+*/
+class Extension
+ {
+ public:
+ virtual Handshake_Extension_Type type() const = 0;
+
+ virtual std::vector<byte> serialize() const = 0;
+
+ virtual bool empty() const = 0;
+
+ virtual ~Extension() {}
+ };
+
+/**
+* Server Name Indicator extension (RFC 3546)
+*/
+class Server_Name_Indicator : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SERVER_NAME_INDICATION; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ Server_Name_Indicator(const std::string& host_name) :
+ sni_host_name(host_name) {}
+
+ Server_Name_Indicator(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ std::string host_name() const { return sni_host_name; }
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return sni_host_name == ""; }
+ private:
+ std::string sni_host_name;
+ };
+
+/**
+* SRP identifier extension (RFC 5054)
+*/
+class SRP_Identifier : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SRP_IDENTIFIER; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ SRP_Identifier(const std::string& identifier) :
+ srp_identifier(identifier) {}
+
+ SRP_Identifier(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ std::string identifier() const { return srp_identifier; }
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return srp_identifier == ""; }
+ private:
+ std::string srp_identifier;
+ };
+
+/**
+* Renegotiation Indication Extension (RFC 5746)
+*/
+class Renegotation_Extension : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SAFE_RENEGOTIATION; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ Renegotation_Extension() {}
+
+ Renegotation_Extension(const std::vector<byte>& bits) :
+ reneg_data(bits) {}
+
+ Renegotation_Extension(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ const std::vector<byte>& renegotiation_info() const
+ { return reneg_data; }
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return false; } // always send this
+ private:
+ std::vector<byte> reneg_data;
+ };
+
+/**
+* Maximum Fragment Length Negotiation Extension (RFC 4366 sec 3.2)
+*/
+class Maximum_Fragment_Length : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_MAX_FRAGMENT_LENGTH; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ bool empty() const { return val != 0; }
+
+ size_t fragment_size() const;
+
+ std::vector<byte> serialize() const
+ {
+ return std::vector<byte>(1, val);
+ }
+
+ /**
+ * @param max_fragment specifies what maximum fragment size to
+ * advertise. Currently must be one of 512, 1024, 2048, or
+ * 4096.
+ */
+ Maximum_Fragment_Length(size_t max_fragment);
+
+ Maximum_Fragment_Length(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ private:
+ byte val;
+ };
+
+/**
+* Next Protocol Negotiation
+* http://technotes.googlecode.com/git/nextprotoneg.html
+*
+* This implementation requires the semantics defined in the Google
+* spec (implemented in Chromium); the internet draft leaves the format
+* unspecified.
+*/
+class Next_Protocol_Notification : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_NEXT_PROTOCOL; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ const std::vector<std::string>& protocols() const
+ { return m_protocols; }
+
+ /**
+ * Empty extension, used by client
+ */
+ Next_Protocol_Notification() {}
+
+ /**
+ * List of protocols, used by server
+ */
+ Next_Protocol_Notification(const std::vector<std::string>& protocols) :
+ m_protocols(protocols) {}
+
+ Next_Protocol_Notification(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return false; }
+ private:
+ std::vector<std::string> m_protocols;
+ };
+
+class Session_Ticket : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SESSION_TICKET; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ const std::vector<byte>& contents() const { return m_ticket; }
+
+ /**
+ * Create empty extension, used by both client and server
+ */
+ Session_Ticket() {}
+
+ /**
+ * Extension with ticket, used by client
+ */
+ Session_Ticket(const std::vector<byte>& session_ticket) :
+ m_ticket(session_ticket) {}
+
+ /**
+ * Deserialize a session ticket
+ */
+ Session_Ticket(TLS_Data_Reader& reader, u16bit extension_size);
+
+ std::vector<byte> serialize() const { return m_ticket; }
+
+ bool empty() const { return false; }
+ private:
+ std::vector<byte> m_ticket;
+ };
+
+/**
+* Supported Elliptic Curves Extension (RFC 4492)
+*/
+class Supported_Elliptic_Curves : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_USABLE_ELLIPTIC_CURVES; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ static std::string curve_id_to_name(u16bit id);
+ static u16bit name_to_curve_id(const std::string& name);
+
+ const std::vector<std::string>& curves() const { return m_curves; }
+
+ std::vector<byte> serialize() const;
+
+ Supported_Elliptic_Curves(const std::vector<std::string>& curves) :
+ m_curves(curves) {}
+
+ Supported_Elliptic_Curves(TLS_Data_Reader& reader,
+ u16bit extension_size);
+
+ bool empty() const { return m_curves.empty(); }
+ private:
+ std::vector<std::string> m_curves;
+ };
+
+/**
+* Signature Algorithms Extension for TLS 1.2 (RFC 5246)
+*/
+class Signature_Algorithms : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SIGNATURE_ALGORITHMS; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ static std::string hash_algo_name(byte code);
+ static byte hash_algo_code(const std::string& name);
+
+ static std::string sig_algo_name(byte code);
+ static byte sig_algo_code(const std::string& name);
+
+ std::vector<std::pair<std::string, std::string> >
+ supported_signature_algorthms() const
+ {
+ return m_supported_algos;
+ }
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return false; }
+
+ Signature_Algorithms(const std::vector<std::pair<std::string, std::string> >& algos) :
+ m_supported_algos(algos) {}
+
+ Signature_Algorithms(TLS_Data_Reader& reader,
+ u16bit extension_size);
+ private:
+ std::vector<std::pair<std::string, std::string> > m_supported_algos;
+ };
+
+/**
+* Heartbeat Extension (RFC 6520)
+*/
+class Heartbeat_Support_Indicator : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_HEARTBEAT_SUPPORT; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ bool peer_allowed_to_send() const { return m_peer_allowed_to_send; }
+
+ std::vector<byte> serialize() const;
+
+ bool empty() const { return false; }
+
+ Heartbeat_Support_Indicator(bool peer_allowed_to_send) :
+ m_peer_allowed_to_send(peer_allowed_to_send) {}
+
+ Heartbeat_Support_Indicator(TLS_Data_Reader& reader, u16bit extension_size);
+
+ private:
+ bool m_peer_allowed_to_send;
+ };
+
+/**
+* Represents a block of extensions in a hello message
+*/
+class Extensions
+ {
+ public:
+ template<typename T>
+ T* get() const
+ {
+ Handshake_Extension_Type type = T::static_type();
+
+ std::map<Handshake_Extension_Type, Extension*>::const_iterator i =
+ extensions.find(type);
+
+ if(i != extensions.end())
+ return dynamic_cast<T*>(i->second);
+ return nullptr;
+ }
+
+ void add(Extension* extn)
+ {
+ delete extensions[extn->type()]; // or hard error if already exists?
+ extensions[extn->type()] = extn;
+ }
+
+ std::vector<byte> serialize() const;
+
+ Extensions() {}
+
+ Extensions(TLS_Data_Reader& reader); // deserialize
+
+ ~Extensions();
+ private:
+ Extensions(const Extensions&) {}
+ Extensions& operator=(const Extensions&) { return (*this); }
+
+ std::map<Handshake_Extension_Type, Extension*> extensions;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp
new file mode 100644
index 000000000..df956e7bb
--- /dev/null
+++ b/src/tls/tls_handshake_hash.cpp
@@ -0,0 +1,103 @@
+/*
+* TLS Handshake Hash
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_handshake_hash.h>
+#include <botan/tls_exceptn.h>
+#include <botan/libstate.h>
+#include <botan/hash.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+void Handshake_Hash::update(Handshake_Type handshake_type,
+ const std::vector<byte>& handshake_msg)
+ {
+ update(static_cast<byte>(handshake_type));
+
+ const size_t record_length = handshake_msg.size();
+ for(size_t i = 0; i != 3; i++)
+ update(get_byte<u32bit>(i+1, record_length));
+
+ update(handshake_msg);
+ }
+
+/**
+* Return a TLS Handshake Hash
+*/
+secure_vector<byte> Handshake_Hash::final(Protocol_Version version,
+ const std::string& mac_algo)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ std::unique_ptr<HashFunction> hash;
+
+ if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11)
+ {
+ hash.reset(af.make_hash_function("TLS.Digest.0"));
+ }
+ else if(version == Protocol_Version::TLS_V12)
+ {
+ if(mac_algo == "MD5" || mac_algo == "SHA-1" || mac_algo == "SHA-256")
+ hash.reset(af.make_hash_function("SHA-256"));
+ else
+ hash.reset(af.make_hash_function(mac_algo));
+ }
+ else
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Unknown version for handshake hashes");
+
+ hash->update(data);
+ return hash->final();
+ }
+
+/**
+* Return a SSLv3 Handshake Hash
+*/
+secure_vector<byte> Handshake_Hash::final_ssl3(const secure_vector<byte>& secret)
+ {
+ const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C;
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ std::unique_ptr<HashFunction> md5(af.make_hash_function("MD5"));
+ std::unique_ptr<HashFunction> sha1(af.make_hash_function("SHA-1"));
+
+ md5->update(data);
+ sha1->update(data);
+
+ md5->update(secret);
+ sha1->update(secret);
+
+ for(size_t i = 0; i != 48; ++i)
+ md5->update(PAD_INNER);
+ for(size_t i = 0; i != 40; ++i)
+ sha1->update(PAD_INNER);
+
+ secure_vector<byte> inner_md5 = md5->final(), inner_sha1 = sha1->final();
+
+ md5->update(secret);
+ sha1->update(secret);
+
+ for(size_t i = 0; i != 48; ++i)
+ md5->update(PAD_OUTER);
+ for(size_t i = 0; i != 40; ++i)
+ sha1->update(PAD_OUTER);
+
+ md5->update(inner_md5);
+ sha1->update(inner_sha1);
+
+ secure_vector<byte> output;
+ output += md5->final();
+ output += sha1->final();
+ return output;
+ }
+
+}
+
+}
diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h
new file mode 100644
index 000000000..02943977f
--- /dev/null
+++ b/src/tls/tls_handshake_hash.h
@@ -0,0 +1,58 @@
+/*
+* TLS Handshake Hash
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_HANDSHAKE_HASH_H__
+#define BOTAN_TLS_HANDSHAKE_HASH_H__
+
+#include <botan/secmem.h>
+#include <botan/tls_version.h>
+#include <botan/tls_magic.h>
+
+namespace Botan {
+
+namespace TLS {
+
+using namespace Botan;
+
+/**
+* TLS Handshake Hash
+*/
+class Handshake_Hash
+ {
+ public:
+ void update(const byte in[], size_t length)
+ { data += std::make_pair(in, length); }
+
+ void update(const secure_vector<byte>& in)
+ { data += in; }
+
+ void update(const std::vector<byte>& in)
+ { data += in; }
+
+ void update(byte in)
+ { data.push_back(in); }
+
+ void update(Handshake_Type handshake_type,
+ const std::vector<byte>& handshake_msg);
+
+ secure_vector<byte> final(Protocol_Version version,
+ const std::string& mac_algo);
+
+ secure_vector<byte> final_ssl3(const secure_vector<byte>& master_secret);
+
+ const secure_vector<byte>& get_contents() const
+ { return data; }
+
+ private:
+ secure_vector<byte> data;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_handshake_reader.cpp b/src/tls/tls_handshake_reader.cpp
new file mode 100644
index 000000000..a3fe48f71
--- /dev/null
+++ b/src/tls/tls_handshake_reader.cpp
@@ -0,0 +1,66 @@
+/*
+* TLS Handshake Reader
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_handshake_reader.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace TLS {
+
+void Stream_Handshake_Reader::add_input(const byte record[],
+ size_t record_size)
+ {
+ m_queue.write(record, record_size);
+ }
+
+bool Stream_Handshake_Reader::empty() const
+ {
+ return m_queue.empty();
+ }
+
+bool Stream_Handshake_Reader::have_full_record() const
+ {
+ if(m_queue.size() >= 4)
+ {
+ byte head[4] = { 0 };
+ m_queue.peek(head, 4);
+
+ const size_t length = make_u32bit(0, head[1], head[2], head[3]);
+
+ return (m_queue.size() >= length + 4);
+ }
+
+ return false;
+ }
+
+std::pair<Handshake_Type, std::vector<byte> > Stream_Handshake_Reader::get_next_record()
+ {
+ if(m_queue.size() >= 4)
+ {
+ byte head[4] = { 0 };
+ m_queue.peek(head, 4);
+
+ const size_t length = make_u32bit(0, head[1], head[2], head[3]);
+
+ if(m_queue.size() >= length + 4)
+ {
+ Handshake_Type type = static_cast<Handshake_Type>(head[0]);
+ std::vector<byte> contents(length);
+ m_queue.read(head, 4); // discard
+ m_queue.read(&contents[0], contents.size());
+
+ return std::make_pair(type, contents);
+ }
+ }
+
+ throw Internal_Error("Stream_Handshake_Reader::get_next_record called without a full record");
+ }
+
+}
+
+}
diff --git a/src/tls/tls_handshake_reader.h b/src/tls/tls_handshake_reader.h
new file mode 100644
index 000000000..618e1878a
--- /dev/null
+++ b/src/tls/tls_handshake_reader.h
@@ -0,0 +1,58 @@
+/*
+* TLS Handshake Reader
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_HANDSHAKE_READER_H__
+#define BOTAN_TLS_HANDSHAKE_READER_H__
+
+#include <botan/tls_magic.h>
+#include <botan/secqueue.h>
+#include <botan/loadstor.h>
+#include <utility>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Handshake Reader Interface
+*/
+class Handshake_Reader
+ {
+ public:
+ virtual void add_input(const byte record[], size_t record_size) = 0;
+
+ virtual bool empty() const = 0;
+
+ virtual bool have_full_record() const = 0;
+
+ virtual std::pair<Handshake_Type, std::vector<byte> > get_next_record() = 0;
+
+ virtual ~Handshake_Reader() {}
+ };
+
+/**
+* Reader of TLS handshake messages
+*/
+class Stream_Handshake_Reader : public Handshake_Reader
+ {
+ public:
+ void add_input(const byte record[], size_t record_size);
+
+ bool empty() const;
+
+ bool have_full_record() const;
+
+ std::pair<Handshake_Type, std::vector<byte> > get_next_record();
+ private:
+ SecureQueue m_queue;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp
new file mode 100644
index 000000000..90de7c3f9
--- /dev/null
+++ b/src/tls/tls_handshake_state.cpp
@@ -0,0 +1,330 @@
+/*
+* TLS Handshaking
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/assert.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+u32bit bitmask_for_handshake_type(Handshake_Type type)
+ {
+ switch(type)
+ {
+ case HELLO_REQUEST:
+ return (1 << 0);
+
+ /*
+ * Same code point for both client hello styles
+ */
+ case CLIENT_HELLO:
+ case CLIENT_HELLO_SSLV2:
+ return (1 << 1);
+
+ case SERVER_HELLO:
+ return (1 << 2);
+
+ case CERTIFICATE:
+ return (1 << 3);
+
+ case SERVER_KEX:
+ return (1 << 4);
+
+ case CERTIFICATE_REQUEST:
+ return (1 << 5);
+
+ case SERVER_HELLO_DONE:
+ return (1 << 6);
+
+ case CERTIFICATE_VERIFY:
+ return (1 << 7);
+
+ case CLIENT_KEX:
+ return (1 << 8);
+
+ case NEXT_PROTOCOL:
+ return (1 << 9);
+
+ case NEW_SESSION_TICKET:
+ return (1 << 10);
+
+ case HANDSHAKE_CCS:
+ return (1 << 11);
+
+ case FINISHED:
+ return (1 << 12);
+
+ // allow explicitly disabling new handshakes
+ case HANDSHAKE_NONE:
+ return 0;
+
+ default:
+ throw Internal_Error("Unknown handshake type " +
+ std::to_string(type));
+ }
+
+ return 0;
+ }
+
+}
+
+/*
+* Initialize the SSL/TLS Handshake State
+*/
+Handshake_State::Handshake_State(Handshake_Reader* reader)
+ {
+ client_hello = nullptr;
+ server_hello = nullptr;
+ server_certs = nullptr;
+ server_kex = nullptr;
+ cert_req = nullptr;
+ server_hello_done = nullptr;
+ next_protocol = nullptr;
+ new_session_ticket = nullptr;
+
+ client_certs = nullptr;
+ client_kex = nullptr;
+ client_verify = nullptr;
+ client_finished = nullptr;
+ server_finished = nullptr;
+
+ m_handshake_reader = reader;
+
+ server_rsa_kex_key = nullptr;
+
+ m_version = Protocol_Version::SSL_V3;
+
+ hand_expecting_mask = 0;
+ hand_received_mask = 0;
+
+ allow_session_resumption = true;
+ }
+
+void Handshake_State::set_version(const Protocol_Version& version)
+ {
+ m_version = version;
+ }
+
+void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg)
+ {
+ const u32bit mask = bitmask_for_handshake_type(handshake_msg);
+
+ hand_received_mask |= mask;
+
+ const bool ok = (hand_expecting_mask & mask); // overlap?
+
+ if(!ok)
+ throw Unexpected_Message("Unexpected state transition in handshake, got " +
+ std::to_string(handshake_msg) + " mask is " +
+ std::to_string(hand_expecting_mask));
+
+ /* We don't know what to expect next, so force a call to
+ set_expected_next; if it doesn't happen, the next transition
+ check will always fail which is what we want.
+ */
+ hand_expecting_mask = 0;
+ }
+
+void Handshake_State::set_expected_next(Handshake_Type handshake_msg)
+ {
+ hand_expecting_mask |= bitmask_for_handshake_type(handshake_msg);
+ }
+
+bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const
+ {
+ const u32bit mask = bitmask_for_handshake_type(handshake_msg);
+
+ return (hand_received_mask & mask);
+ }
+
+std::string Handshake_State::srp_identifier() const
+ {
+ if(suite.valid() && suite.kex_algo() == "SRP_SHA")
+ return client_hello->srp_identifier();
+
+ return "";
+ }
+
+const std::vector<byte>& Handshake_State::session_ticket() const
+ {
+ if(new_session_ticket && !new_session_ticket->ticket().empty())
+ return new_session_ticket->ticket();
+
+ return client_hello->session_ticket();
+ }
+
+KDF* Handshake_State::protocol_specific_prf()
+ {
+ if(version() == Protocol_Version::SSL_V3)
+ {
+ return get_kdf("SSL3-PRF");
+ }
+ else if(version() == Protocol_Version::TLS_V10 || version() == Protocol_Version::TLS_V11)
+ {
+ return get_kdf("TLS-PRF");
+ }
+ else if(version() == Protocol_Version::TLS_V12)
+ {
+ if(suite.mac_algo() == "MD5" ||
+ suite.mac_algo() == "SHA-1" ||
+ suite.mac_algo() == "SHA-256")
+ {
+ return get_kdf("TLS-12-PRF(SHA-256)");
+ }
+
+ return get_kdf("TLS-12-PRF(" + suite.mac_algo() + ")");
+ }
+
+ throw Internal_Error("Unknown version code " + version().to_string());
+ }
+
+std::pair<std::string, Signature_Format>
+Handshake_State::choose_sig_format(const Private_Key* key,
+ std::string& hash_algo_out,
+ std::string& sig_algo_out,
+ bool for_client_auth)
+ {
+ const std::string sig_algo = key->algo_name();
+
+ const std::vector<std::pair<std::string, std::string> > supported_algos =
+ (for_client_auth) ? cert_req->supported_algos() : client_hello->supported_algos();
+
+ std::string hash_algo;
+
+ for(size_t i = 0; i != supported_algos.size(); ++i)
+ {
+ if(supported_algos[i].second == sig_algo)
+ {
+ hash_algo = supported_algos[i].first;
+ break;
+ }
+ }
+
+ if(for_client_auth && this->version() == Protocol_Version::SSL_V3)
+ hash_algo = "Raw";
+
+ if(hash_algo == "" && this->version() == Protocol_Version::TLS_V12)
+ hash_algo = "SHA-1"; // TLS 1.2 but no compatible hashes set (?)
+
+ BOTAN_ASSERT(hash_algo != "", "Couldn't figure out hash to use");
+
+ if(this->version() >= Protocol_Version::TLS_V12)
+ {
+ hash_algo_out = hash_algo;
+ sig_algo_out = sig_algo;
+ }
+
+ if(sig_algo == "RSA")
+ {
+ const std::string padding = "EMSA3(" + hash_algo + ")";
+
+ return std::make_pair(padding, IEEE_1363);
+ }
+ else if(sig_algo == "DSA" || sig_algo == "ECDSA")
+ {
+ const std::string padding = "EMSA1(" + hash_algo + ")";
+
+ return std::make_pair(padding, DER_SEQUENCE);
+ }
+
+ throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures");
+ }
+
+std::pair<std::string, Signature_Format>
+Handshake_State::understand_sig_format(const Public_Key* key,
+ std::string hash_algo,
+ std::string sig_algo,
+ bool for_client_auth)
+ {
+ const std::string algo_name = key->algo_name();
+
+ /*
+ FIXME: This should check what was sent against the client hello
+ preferences, or the certificate request, to ensure it was allowed
+ by those restrictions.
+
+ Or not?
+ */
+
+ if(this->version() < Protocol_Version::TLS_V12)
+ {
+ if(hash_algo != "" || sig_algo != "")
+ throw Decoding_Error("Counterparty sent hash/sig IDs with old version");
+ }
+ else
+ {
+ if(hash_algo == "")
+ throw Decoding_Error("Counterparty did not send hash/sig IDS");
+
+ if(sig_algo != algo_name)
+ throw Decoding_Error("Counterparty sent inconsistent key and sig types");
+ }
+
+ if(algo_name == "RSA")
+ {
+ if(for_client_auth && this->version() == Protocol_Version::SSL_V3)
+ {
+ hash_algo = "Raw";
+ }
+ else if(this->version() < Protocol_Version::TLS_V12)
+ {
+ hash_algo = "TLS.Digest.0";
+ }
+
+ const std::string padding = "EMSA3(" + hash_algo + ")";
+ return std::make_pair(padding, IEEE_1363);
+ }
+ else if(algo_name == "DSA" || algo_name == "ECDSA")
+ {
+ if(algo_name == "DSA" && for_client_auth && this->version() == Protocol_Version::SSL_V3)
+ {
+ hash_algo = "Raw";
+ }
+ else if(this->version() < Protocol_Version::TLS_V12)
+ {
+ hash_algo = "SHA-1";
+ }
+
+ const std::string padding = "EMSA1(" + hash_algo + ")";
+
+ return std::make_pair(padding, DER_SEQUENCE);
+ }
+
+ throw Invalid_Argument(algo_name + " is invalid/unknown for TLS signatures");
+ }
+
+/*
+* Destroy the SSL/TLS Handshake State
+*/
+Handshake_State::~Handshake_State()
+ {
+ delete client_hello;
+ delete server_hello;
+ delete server_certs;
+ delete server_kex;
+ delete cert_req;
+ delete server_hello_done;
+ delete next_protocol;
+ delete new_session_ticket;
+
+ delete client_certs;
+ delete client_kex;
+ delete client_verify;
+ delete client_finished;
+ delete server_finished;
+
+ delete m_handshake_reader;
+ }
+
+}
+
+}
diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h
new file mode 100644
index 000000000..ef8b4ee8f
--- /dev/null
+++ b/src/tls/tls_handshake_state.h
@@ -0,0 +1,112 @@
+/*
+* TLS Handshake State
+* (C) 2004-2006 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_HANDSHAKE_STATE_H__
+#define BOTAN_TLS_HANDSHAKE_STATE_H__
+
+#include <botan/internal/tls_handshake_hash.h>
+#include <botan/internal/tls_handshake_reader.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/pk_keys.h>
+#include <botan/pubkey.h>
+
+#include <functional>
+#include <utility>
+
+namespace Botan {
+
+class KDF;
+
+namespace TLS {
+
+/**
+* SSL/TLS Handshake State
+*/
+class Handshake_State
+ {
+ public:
+ Handshake_State(Handshake_Reader* reader);
+ ~Handshake_State();
+
+ bool received_handshake_msg(Handshake_Type handshake_msg) const;
+
+ void confirm_transition_to(Handshake_Type handshake_msg);
+ void set_expected_next(Handshake_Type handshake_msg);
+
+ const std::vector<byte>& session_ticket() const;
+
+ std::pair<std::string, Signature_Format>
+ understand_sig_format(const Public_Key* key,
+ std::string hash_algo,
+ std::string sig_algo,
+ bool for_client_auth);
+
+ std::pair<std::string, Signature_Format>
+ choose_sig_format(const Private_Key* key,
+ std::string& hash_algo,
+ std::string& sig_algo,
+ bool for_client_auth);
+
+ std::string srp_identifier() const;
+
+ KDF* protocol_specific_prf();
+
+ Protocol_Version version() const { return m_version; }
+
+ void set_version(const Protocol_Version& version);
+
+ class Client_Hello* client_hello;
+ class Server_Hello* server_hello;
+ class Certificate* server_certs;
+ class Server_Key_Exchange* server_kex;
+ class Certificate_Req* cert_req;
+ class Server_Hello_Done* server_hello_done;
+
+ class Certificate* client_certs;
+ class Client_Key_Exchange* client_kex;
+ class Certificate_Verify* client_verify;
+
+ class Next_Protocol* next_protocol;
+ class New_Session_Ticket* new_session_ticket;
+
+ class Finished* client_finished;
+ class Finished* server_finished;
+
+ // Used by the server only, in case of RSA key exchange
+ Private_Key* server_rsa_kex_key;
+
+ Ciphersuite suite;
+ Session_Keys keys;
+ Handshake_Hash hash;
+
+ /*
+ * Only used by clients for session resumption
+ */
+ secure_vector<byte> resume_master_secret;
+
+ /*
+ *
+ */
+ bool allow_session_resumption;
+
+ /**
+ * Used by client using NPN
+ */
+ std::function<std::string (std::vector<std::string>)> client_npn_cb;
+
+ Handshake_Reader* handshake_reader() { return m_handshake_reader; }
+ private:
+ Handshake_Reader* m_handshake_reader;
+ u32bit hand_expecting_mask, hand_received_mask;
+ Protocol_Version m_version;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_heartbeats.cpp b/src/tls/tls_heartbeats.cpp
new file mode 100644
index 000000000..8c129858e
--- /dev/null
+++ b/src/tls/tls_heartbeats.cpp
@@ -0,0 +1,78 @@
+/*
+* TLS Heartbeats
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_heartbeats.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/tls_exceptn.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Heartbeat_Message::Heartbeat_Message(const std::vector<byte>& buf)
+ {
+ TLS_Data_Reader reader(buf);
+
+ const byte type = reader.get_byte();
+
+ if(type != 1 && type != 2)
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Unknown heartbeat message type");
+
+ m_type = static_cast<Type>(type);
+
+ m_payload = reader.get_range<byte>(2, 0, 16*1024);
+
+ // padding follows and is ignored
+ }
+
+Heartbeat_Message::Heartbeat_Message(Type type,
+ const byte payload[],
+ size_t payload_len) :
+ m_type(type),
+ m_payload(payload, payload + payload_len)
+ {
+ }
+
+std::vector<byte> Heartbeat_Message::contents() const
+ {
+ std::vector<byte> send_buf(3 + m_payload.size() + 16);
+ send_buf[0] = m_type;
+ send_buf[1] = get_byte<u16bit>(0, m_payload.size());
+ send_buf[2] = get_byte<u16bit>(1, m_payload.size());
+ copy_mem(&send_buf[3], &m_payload[0], m_payload.size());
+ // leave padding as all zeros
+
+ return send_buf;
+ }
+
+std::vector<byte> Heartbeat_Support_Indicator::serialize() const
+ {
+ std::vector<byte> heartbeat(1);
+ heartbeat[0] = (m_peer_allowed_to_send ? 1 : 2);
+ return heartbeat;
+ }
+
+Heartbeat_Support_Indicator::Heartbeat_Support_Indicator(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ if(extension_size != 1)
+ throw Decoding_Error("Strange size for heartbeat extension");
+
+ const byte code = reader.get_byte();
+
+ if(code != 1 && code != 2)
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Unknown heartbeat code " + std::to_string(code));
+
+ m_peer_allowed_to_send = (code == 1);
+ }
+
+}
+
+}
diff --git a/src/tls/tls_heartbeats.h b/src/tls/tls_heartbeats.h
new file mode 100644
index 000000000..f3cc9ec68
--- /dev/null
+++ b/src/tls/tls_heartbeats.h
@@ -0,0 +1,40 @@
+/*
+* TLS Heartbeats
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_HEARTBEATS_H__
+#define BOTAN_TLS_HEARTBEATS_H__
+
+#include <botan/secmem.h>
+
+namespace Botan {
+
+namespace TLS {
+
+class Heartbeat_Message
+ {
+ public:
+ enum Type { REQUEST = 1, RESPONSE = 2 };
+
+ std::vector<byte> contents() const;
+
+ const std::vector<byte>& payload() const { return m_payload; }
+
+ bool is_request() const { return m_type == REQUEST; }
+
+ Heartbeat_Message(const std::vector<byte>& buf);
+
+ Heartbeat_Message(Type type, const byte payload[], size_t payload_len);
+ private:
+ Type m_type;
+ std::vector<byte> m_payload;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h
new file mode 100644
index 000000000..2972321c9
--- /dev/null
+++ b/src/tls/tls_magic.h
@@ -0,0 +1,69 @@
+/*
+* SSL/TLS Protocol Constants
+* (C) 2004-2010 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_PROTOCOL_MAGIC_H__
+#define BOTAN_TLS_PROTOCOL_MAGIC_H__
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Protocol Constants for SSL/TLS
+*/
+enum Size_Limits {
+ TLS_HEADER_SIZE = 5,
+ MAX_PLAINTEXT_SIZE = 16*1024,
+ MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024,
+ MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024,
+
+ MAX_TLS_RECORD_SIZE = MAX_CIPHERTEXT_SIZE + TLS_HEADER_SIZE,
+};
+
+enum Connection_Side { CLIENT = 1, SERVER = 2 };
+
+enum Record_Type {
+ CONNECTION_CLOSED = 0,
+
+ CHANGE_CIPHER_SPEC = 20,
+ ALERT = 21,
+ HANDSHAKE = 22,
+ APPLICATION_DATA = 23,
+ HEARTBEAT = 24,
+};
+
+enum Handshake_Type {
+ HELLO_REQUEST = 0,
+ CLIENT_HELLO = 1,
+ CLIENT_HELLO_SSLV2 = 253, // Not a wire value
+ SERVER_HELLO = 2,
+ HELLO_VERIFY_REQUEST = 3,
+ NEW_SESSION_TICKET = 4, // RFC 5077
+ CERTIFICATE = 11,
+ SERVER_KEX = 12,
+ CERTIFICATE_REQUEST = 13,
+ SERVER_HELLO_DONE = 14,
+ CERTIFICATE_VERIFY = 15,
+ CLIENT_KEX = 16,
+ FINISHED = 20,
+
+ NEXT_PROTOCOL = 67,
+
+ HANDSHAKE_CCS = 254, // Not a wire value
+ HANDSHAKE_NONE = 255 // Null value
+};
+
+enum Compression_Method {
+ NO_COMPRESSION = 0x00,
+ DEFLATE_COMPRESSION = 0x01
+};
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
new file mode 100644
index 000000000..31c35d901
--- /dev/null
+++ b/src/tls/tls_messages.h
@@ -0,0 +1,501 @@
+/*
+* TLS Messages
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_MESSAGES_H__
+#define BOTAN_TLS_MESSAGES_H__
+
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/tls_session.h>
+#include <botan/tls_policy.h>
+#include <botan/tls_magic.h>
+#include <botan/tls_ciphersuite.h>
+#include <botan/bigint.h>
+#include <botan/pkcs8.h>
+#include <botan/x509cert.h>
+#include <vector>
+
+namespace Botan {
+
+class Credentials_Manager;
+class SRP6_Server_Session;
+
+namespace TLS {
+
+class Record_Writer;
+class Record_Reader;
+
+/**
+* TLS Handshake Message Base Class
+*/
+class Handshake_Message
+ {
+ public:
+ virtual std::vector<byte> serialize() const = 0;
+ virtual Handshake_Type type() const = 0;
+
+ Handshake_Message() {}
+ virtual ~Handshake_Message() {}
+ private:
+ Handshake_Message(const Handshake_Message&) {}
+ Handshake_Message& operator=(const Handshake_Message&) { return (*this); }
+ };
+
+std::vector<byte> make_hello_random(RandomNumberGenerator& rng);
+
+/**
+* DTLS Hello Verify Request
+*/
+class Hello_Verify_Request : public Handshake_Message
+ {
+ public:
+ std::vector<byte> serialize() const;
+ Handshake_Type type() const { return HELLO_VERIFY_REQUEST; }
+
+ std::vector<byte> cookie() const { return m_cookie; }
+
+ Hello_Verify_Request(const std::vector<byte>& buf);
+
+ Hello_Verify_Request(const std::vector<byte>& client_hello_bits,
+ const std::string& client_identity,
+ const SymmetricKey& secret_key);
+ private:
+ std::vector<byte> m_cookie;
+ };
+
+/**
+* Client Hello Message
+*/
+class Client_Hello : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return CLIENT_HELLO; }
+
+ Protocol_Version version() const { return m_version; }
+
+ const std::vector<byte>& session_id() const { return m_session_id; }
+
+ const std::vector<std::pair<std::string, std::string> >& supported_algos() const
+ { return m_supported_algos; }
+
+ const std::vector<std::string>& supported_ecc_curves() const
+ { return m_supported_curves; }
+
+ std::vector<u16bit> ciphersuites() const { return m_suites; }
+ std::vector<byte> compression_methods() const { return m_comp_methods; }
+
+ const std::vector<byte>& random() const { return m_random; }
+
+ std::string sni_hostname() const { return m_hostname; }
+
+ std::string srp_identifier() const { return m_srp_identifier; }
+
+ bool secure_renegotiation() const { return m_secure_renegotiation; }
+
+ const std::vector<byte>& renegotiation_info()
+ { return m_renegotiation_info; }
+
+ bool offered_suite(u16bit ciphersuite) const;
+
+ bool next_protocol_notification() const { return m_next_protocol; }
+
+ size_t fragment_size() const { return m_fragment_size; }
+
+ bool supports_session_ticket() const { return m_supports_session_ticket; }
+
+ const std::vector<byte>& session_ticket() const
+ { return m_session_ticket; }
+
+ bool supports_heartbeats() const { return m_supports_heartbeats; }
+
+ bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; }
+
+ Client_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<byte>& reneg_info,
+ bool next_protocol = false,
+ const std::string& hostname = "",
+ const std::string& srp_identifier = "");
+
+ Client_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<byte>& reneg_info,
+ const Session& resumed_session,
+ bool next_protocol = false);
+
+ Client_Hello(const std::vector<byte>& buf,
+ Handshake_Type type);
+
+ private:
+ std::vector<byte> serialize() const;
+ void deserialize(const std::vector<byte>& buf);
+ void deserialize_sslv2(const std::vector<byte>& buf);
+
+ Protocol_Version m_version;
+ std::vector<byte> m_session_id, m_random;
+ std::vector<u16bit> m_suites;
+ std::vector<byte> m_comp_methods;
+ std::string m_hostname;
+ std::string m_srp_identifier;
+ bool m_next_protocol;
+
+ size_t m_fragment_size;
+ bool m_secure_renegotiation;
+ std::vector<byte> m_renegotiation_info;
+
+ std::vector<std::pair<std::string, std::string> > m_supported_algos;
+ std::vector<std::string> m_supported_curves;
+
+ bool m_supports_session_ticket;
+ std::vector<byte> m_session_ticket;
+
+ bool m_supports_heartbeats;
+ bool m_peer_can_send_heartbeats;
+ };
+
+/**
+* Server Hello Message
+*/
+class Server_Hello : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return SERVER_HELLO; }
+
+ Protocol_Version version() { return m_version; }
+
+ const std::vector<byte>& random() const { return m_random; }
+
+ const std::vector<byte>& session_id() const { return m_session_id; }
+
+ u16bit ciphersuite() const { return m_ciphersuite; }
+
+ byte compression_method() const { return m_comp_method; }
+
+ bool secure_renegotiation() const { return m_secure_renegotiation; }
+
+ bool next_protocol_notification() const { return m_next_protocol; }
+
+ bool supports_session_ticket() const { return m_supports_session_ticket; }
+
+ const std::vector<std::string>& next_protocols() const
+ { return m_next_protocols; }
+
+ size_t fragment_size() const { return m_fragment_size; }
+
+ const std::vector<byte>& renegotiation_info()
+ { return m_renegotiation_info; }
+
+ bool supports_heartbeats() const { return m_supports_heartbeats; }
+
+ bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; }
+
+ Server_Hello(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<byte>& session_id,
+ Protocol_Version ver,
+ u16bit ciphersuite,
+ byte compression,
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const std::vector<byte>& reneg_info,
+ bool offer_session_ticket,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ bool client_has_heartbeat,
+ RandomNumberGenerator& rng);
+
+ Server_Hello(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+
+ Protocol_Version m_version;
+ std::vector<byte> m_session_id, m_random;
+ u16bit m_ciphersuite;
+ byte m_comp_method;
+
+ size_t m_fragment_size;
+ bool m_secure_renegotiation;
+ std::vector<byte> m_renegotiation_info;
+
+ bool m_next_protocol;
+ std::vector<std::string> m_next_protocols;
+ bool m_supports_session_ticket;
+
+ bool m_supports_heartbeats;
+ bool m_peer_can_send_heartbeats;
+ };
+
+/**
+* Client Key Exchange Message
+*/
+class Client_Key_Exchange : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return CLIENT_KEX; }
+
+ const secure_vector<byte>& pre_master_secret() const
+ { return pre_master; }
+
+ Client_Key_Exchange(Record_Writer& output,
+ Handshake_State* state,
+ Credentials_Manager& creds,
+ const std::vector<X509_Certificate>& peer_certs,
+ const std::string& hostname,
+ RandomNumberGenerator& rng);
+
+ Client_Key_Exchange(const std::vector<byte>& buf,
+ const Handshake_State* state,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng);
+
+ private:
+ std::vector<byte> serialize() const { return key_material; }
+
+ std::vector<byte> key_material;
+ secure_vector<byte> pre_master;
+ };
+
+/**
+* Certificate Message
+*/
+class Certificate : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return CERTIFICATE; }
+ const std::vector<X509_Certificate>& cert_chain() const { return m_certs; }
+
+ size_t count() const { return m_certs.size(); }
+ bool empty() const { return m_certs.empty(); }
+
+ Certificate(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<X509_Certificate>& certs);
+
+ Certificate(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+
+ std::vector<X509_Certificate> m_certs;
+ };
+
+/**
+* Certificate Request Message
+*/
+class Certificate_Req : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return CERTIFICATE_REQUEST; }
+
+ const std::vector<std::string>& acceptable_cert_types() const
+ { return cert_key_types; }
+
+ std::vector<X509_DN> acceptable_CAs() const { return names; }
+
+ std::vector<std::pair<std::string, std::string> > supported_algos() const
+ { return m_supported_algos; }
+
+ Certificate_Req(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ const std::vector<X509_Certificate>& allowed_cas,
+ Protocol_Version version);
+
+ Certificate_Req(const std::vector<byte>& buf,
+ Protocol_Version version);
+ private:
+ std::vector<byte> serialize() const;
+
+ std::vector<X509_DN> names;
+ std::vector<std::string> cert_key_types;
+
+ std::vector<std::pair<std::string, std::string> > m_supported_algos;
+ };
+
+/**
+* Certificate Verify Message
+*/
+class Certificate_Verify : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return CERTIFICATE_VERIFY; }
+
+ /**
+ * Check the signature on a certificate verify message
+ * @param cert the purported certificate
+ * @param state the handshake state
+ */
+ bool verify(const X509_Certificate& cert,
+ Handshake_State* state);
+
+ Certificate_Verify(Record_Writer& writer,
+ Handshake_State* state,
+ RandomNumberGenerator& rng,
+ const Private_Key* key);
+
+ Certificate_Verify(const std::vector<byte>& buf,
+ Protocol_Version version);
+ private:
+ std::vector<byte> serialize() const;
+
+ std::string sig_algo; // sig algo used to create signature
+ std::string hash_algo; // hash used to create signature
+ std::vector<byte> signature;
+ };
+
+/**
+* Finished Message
+*/
+class Finished : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return FINISHED; }
+
+ std::vector<byte> verify_data() const
+ { return verification_data; }
+
+ bool verify(Handshake_State* state,
+ Connection_Side side);
+
+ Finished(Record_Writer& writer,
+ Handshake_State* state,
+ Connection_Side side);
+
+ Finished(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+
+ Connection_Side side;
+ std::vector<byte> verification_data;
+ };
+
+/**
+* Hello Request Message
+*/
+class Hello_Request : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return HELLO_REQUEST; }
+
+ Hello_Request(Record_Writer& writer);
+ Hello_Request(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+ };
+
+/**
+* Server Key Exchange Message
+*/
+class Server_Key_Exchange : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return SERVER_KEX; }
+
+ const std::vector<byte>& params() const { return m_params; }
+
+ bool verify(const X509_Certificate& cert,
+ Handshake_State* state) const;
+
+ // Only valid for certain kex types
+ const Private_Key& server_kex_key() const;
+
+ // Only valid for SRP negotiation
+ SRP6_Server_Session& server_srp_params();
+
+ Server_Key_Exchange(Record_Writer& writer,
+ Handshake_State* state,
+ const Policy& policy,
+ Credentials_Manager& creds,
+ RandomNumberGenerator& rng,
+ const Private_Key* signing_key = nullptr);
+
+ Server_Key_Exchange(const std::vector<byte>& buf,
+ const std::string& kex_alg,
+ const std::string& sig_alg,
+ Protocol_Version version);
+
+ ~Server_Key_Exchange();
+ private:
+ std::vector<byte> serialize() const;
+
+ Private_Key* m_kex_key;
+ SRP6_Server_Session* m_srp_params;
+
+ std::vector<byte> m_params;
+
+ std::string m_sig_algo; // sig algo used to create signature
+ std::string m_hash_algo; // hash used to create signature
+ std::vector<byte> m_signature;
+ };
+
+/**
+* Server Hello Done Message
+*/
+class Server_Hello_Done : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return SERVER_HELLO_DONE; }
+
+ Server_Hello_Done(Record_Writer& writer, Handshake_Hash& hash);
+ Server_Hello_Done(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+ };
+
+/**
+* Next Protocol Message
+*/
+class Next_Protocol : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return NEXT_PROTOCOL; }
+
+ std::string protocol() const { return m_protocol; }
+
+ Next_Protocol(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::string& protocol);
+
+ Next_Protocol(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+
+ std::string m_protocol;
+ };
+
+class New_Session_Ticket : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return NEW_SESSION_TICKET; }
+
+ u32bit ticket_lifetime_hint() const { return m_ticket_lifetime_hint; }
+ const std::vector<byte>& ticket() const { return m_ticket; }
+
+ New_Session_Ticket(Record_Writer& writer,
+ Handshake_Hash& hash,
+ const std::vector<byte>& ticket,
+ u32bit lifetime);
+
+ New_Session_Ticket(Record_Writer& writer,
+ Handshake_Hash& hash);
+
+ New_Session_Ticket(const std::vector<byte>& buf);
+ private:
+ std::vector<byte> serialize() const;
+
+ u32bit m_ticket_lifetime_hint;
+ std::vector<byte> m_ticket;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp
new file mode 100644
index 000000000..f240bebac
--- /dev/null
+++ b/src/tls/tls_policy.cpp
@@ -0,0 +1,265 @@
+/*
+* Policies for TLS
+* (C) 2004-2010,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_policy.h>
+#include <botan/tls_ciphersuite.h>
+#include <botan/tls_magic.h>
+#include <botan/tls_exceptn.h>
+#include <botan/internal/stl_util.h>
+
+namespace Botan {
+
+namespace TLS {
+
+std::vector<std::string> Policy::allowed_ciphers() const
+ {
+ std::vector<std::string> allowed;
+
+ allowed.push_back("AES-256");
+ allowed.push_back("AES-128");
+ allowed.push_back("3DES");
+ allowed.push_back("ARC4");
+ //allowed.push_back("Camellia");
+ //allowed.push_back("SEED");
+
+ return allowed;
+ }
+
+std::vector<std::string> Policy::allowed_hashes() const
+ {
+ std::vector<std::string> allowed;
+
+ allowed.push_back("SHA-512");
+ allowed.push_back("SHA-384");
+ allowed.push_back("SHA-256");
+ allowed.push_back("SHA-224");
+ allowed.push_back("SHA-1");
+ //allowed.push_back("MD5");
+
+ return allowed;
+ }
+
+std::vector<std::string> Policy::allowed_key_exchange_methods() const
+ {
+ std::vector<std::string> allowed;
+
+ allowed.push_back("SRP_SHA");
+ //allowed.push_back("ECDHE_PSK");
+ //allowed.push_back("DHE_PSK");
+ //allowed.push_back("PSK");
+
+ allowed.push_back("ECDH");
+ allowed.push_back("DH");
+ allowed.push_back("RSA");
+
+ return allowed;
+ }
+
+std::vector<std::string> Policy::allowed_signature_methods() const
+ {
+ std::vector<std::string> allowed;
+
+ allowed.push_back("ECDSA");
+ allowed.push_back("RSA");
+ allowed.push_back("DSA");
+ //allowed.push_back("");
+
+ return allowed;
+ }
+
+std::vector<std::string> Policy::allowed_ecc_curves() const
+ {
+ std::vector<std::string> curves;
+ curves.push_back("secp521r1");
+ curves.push_back("secp384r1");
+ curves.push_back("secp256r1");
+ curves.push_back("secp256k1");
+ curves.push_back("secp224r1");
+ curves.push_back("secp224k1");
+ curves.push_back("secp192r1");
+ curves.push_back("secp192k1");
+ curves.push_back("secp160r2");
+ curves.push_back("secp160r1");
+ curves.push_back("secp160k1");
+ return curves;
+ }
+
+/*
+* Choose an ECC curve to use
+*/
+std::string Policy::choose_curve(const std::vector<std::string>& curve_names) const
+ {
+ const std::vector<std::string> our_curves = allowed_ecc_curves();
+
+ for(size_t i = 0; i != our_curves.size(); ++i)
+ if(value_exists(curve_names, our_curves[i]))
+ return our_curves[i];
+
+ return ""; // no shared curve
+ }
+
+DL_Group Policy::dh_group() const
+ {
+ return DL_Group("modp/ietf/2048");
+ }
+
+/*
+* Return allowed compression algorithms
+*/
+std::vector<byte> Policy::compression() const
+ {
+ std::vector<byte> algs;
+ algs.push_back(NO_COMPRESSION);
+ return algs;
+ }
+
+u32bit Policy::session_ticket_lifetime() const
+ {
+ return 86400; // 1 day
+ }
+
+Protocol_Version Policy::min_version() const
+ {
+ return Protocol_Version::SSL_V3;
+ }
+
+Protocol_Version Policy::pref_version() const
+ {
+ return Protocol_Version::TLS_V12;
+ }
+
+namespace {
+
+class Ciphersuite_Preference_Ordering
+ {
+ public:
+ Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
+ const std::vector<std::string>& hashes,
+ const std::vector<std::string>& kex,
+ const std::vector<std::string>& sigs) :
+ m_ciphers(ciphers), m_hashes(hashes), m_kex(kex), m_sigs(sigs) {}
+
+ bool operator()(const Ciphersuite& a, const Ciphersuite& b) const
+ {
+ if(a.kex_algo() != b.kex_algo())
+ {
+ for(size_t i = 0; i != m_kex.size(); ++i)
+ {
+ if(a.kex_algo() == m_kex[i])
+ return true;
+ if(b.kex_algo() == m_kex[i])
+ return false;
+ }
+ }
+
+ if(a.cipher_algo() != b.cipher_algo())
+ {
+ for(size_t i = 0; i != m_ciphers.size(); ++i)
+ {
+ if(a.cipher_algo() == m_ciphers[i])
+ return true;
+ if(b.cipher_algo() == m_ciphers[i])
+ return false;
+ }
+ }
+
+ if(a.cipher_keylen() != b.cipher_keylen())
+ {
+ if(a.cipher_keylen() < b.cipher_keylen())
+ return false;
+ if(a.cipher_keylen() > b.cipher_keylen())
+ return true;
+ }
+
+ if(a.sig_algo() != b.sig_algo())
+ {
+ for(size_t i = 0; i != m_sigs.size(); ++i)
+ {
+ if(a.sig_algo() == m_sigs[i])
+ return true;
+ if(b.sig_algo() == m_sigs[i])
+ return false;
+ }
+ }
+
+ if(a.mac_algo() != b.mac_algo())
+ {
+ for(size_t i = 0; i != m_hashes.size(); ++i)
+ {
+ if(a.mac_algo() == m_hashes[i])
+ return true;
+ if(b.mac_algo() == m_hashes[i])
+ return false;
+ }
+ }
+
+ return false; // equal (?!?)
+ }
+ private:
+ std::vector<std::string> m_ciphers, m_hashes, m_kex, m_sigs;
+
+ };
+
+}
+
+std::vector<u16bit> ciphersuite_list(const Policy& policy,
+ bool have_srp)
+ {
+ const std::vector<std::string> ciphers = policy.allowed_ciphers();
+ const std::vector<std::string> hashes = policy.allowed_hashes();
+ const std::vector<std::string> kex = policy.allowed_key_exchange_methods();
+ const std::vector<std::string> sigs = policy.allowed_signature_methods();
+
+ Ciphersuite_Preference_Ordering order(ciphers, hashes, kex, sigs);
+
+ std::map<Ciphersuite, u16bit, Ciphersuite_Preference_Ordering>
+ ciphersuites(order);
+
+ for(size_t i = 0; i != 65536; ++i)
+ {
+ Ciphersuite suite = Ciphersuite::by_id(i);
+
+ if(!suite.valid())
+ continue; // not a ciphersuite we know, skip
+
+ if(!have_srp && suite.kex_algo() == "SRP_SHA")
+ continue;
+
+ if(!value_exists(kex, suite.kex_algo()))
+ continue; // unsupported key exchange
+
+ if(!value_exists(ciphers, suite.cipher_algo()))
+ continue; // unsupported cipher
+
+ if(!value_exists(hashes, suite.mac_algo()))
+ continue; // unsupported MAC algo
+
+ if(!value_exists(sigs, suite.sig_algo()))
+ {
+ // allow if it's an empty sig algo and we want to use PSK
+ if(suite.sig_algo() != "" || !suite.psk_ciphersuite())
+ continue;
+ }
+
+ // OK, allow it:
+ ciphersuites[suite] = i;
+ }
+
+ std::vector<u16bit> ciphersuite_codes;
+
+ for(std::map<Ciphersuite, u16bit, Ciphersuite_Preference_Ordering>::iterator i = ciphersuites.begin();
+ i != ciphersuites.end(); ++i)
+ {
+ ciphersuite_codes.push_back(i->second);
+ }
+
+ return ciphersuite_codes;
+ }
+
+}
+
+}
diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h
new file mode 100644
index 000000000..c3a0fc29e
--- /dev/null
+++ b/src/tls/tls_policy.h
@@ -0,0 +1,127 @@
+/*
+* Policies
+* (C) 2004-2006 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_POLICY_H__
+#define BOTAN_TLS_POLICY_H__
+
+#include <botan/tls_version.h>
+#include <botan/x509cert.h>
+#include <botan/dl_group.h>
+#include <vector>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* TLS Policy Base Class
+* Inherit and overload as desired to suit local policy concerns
+*/
+class BOTAN_DLL Policy
+ {
+ public:
+
+ /**
+ * Returns a list of ciphers we are willing to negotiate, in
+ * order of preference. Allowed values: any block cipher name, or
+ * ARC4.
+ */
+ virtual std::vector<std::string> allowed_ciphers() const;
+
+ /**
+ * Returns a list of hash algorithms we are willing to use, in
+ * order of preference. This is used for both MACs and signatures.
+ * Allowed values: any hash name, though currently only MD5,
+ * SHA-1, and the SHA-2 variants are used.
+ */
+ virtual std::vector<std::string> allowed_hashes() const;
+
+ /**
+ * Returns a list of key exchange algorithms we are willing to
+ * use, in order of preference. Allowed values: DH, empty string
+ * (representing RSA using server certificate key)
+ */
+ virtual std::vector<std::string> allowed_key_exchange_methods() const;
+
+ /**
+ * Returns a list of signature algorithms we are willing to
+ * use, in order of preference. Allowed values RSA and DSA.
+ */
+ virtual std::vector<std::string> allowed_signature_methods() const;
+
+ /**
+ * Return list of ECC curves we are willing to use in order of preference
+ */
+ virtual std::vector<std::string> allowed_ecc_curves() const;
+
+ /**
+ * Returns a list of signature algorithms we are willing to use,
+ * in order of preference. Allowed values any value of
+ * Compression_Method.
+ */
+ virtual std::vector<byte> compression() const;
+
+ /**
+ * Choose an elliptic curve to use
+ */
+ virtual std::string choose_curve(const std::vector<std::string>& curve_names) const;
+
+ /**
+ * Require support for RFC 5746 extensions to enable
+ * renegotiation.
+ *
+ * @warning Changing this to false exposes you to injected
+ * plaintext attacks. Read the RFC for background.
+ */
+ virtual bool require_secure_renegotiation() const { return true; }
+
+ /**
+ * Return the group to use for ephemeral Diffie-Hellman key agreement
+ */
+ virtual DL_Group dh_group() const;
+
+ /**
+ * If this function returns false, unknown SRP/PSK identifiers
+ * will be rejected with an unknown_psk_identifier alert as soon
+ * as the non-existence is identified. Otherwise, a false
+ * identifier value will be used and the protocol allowed to
+ * proceed, causing the handshake to eventually fail without
+ * revealing that the username does not exist on this system.
+ */
+ virtual bool hide_unknown_users() const { return false; }
+
+ /**
+ * Return the allowed lifetime of a session ticket. If 0, session
+ * tickets do not expire until the session ticket key rolls over.
+ * Expired session tickets cannot be used to resume a session.
+ */
+ virtual u32bit session_ticket_lifetime() const;
+
+ /**
+ * @return the minimum version that we are willing to negotiate
+ */
+ virtual Protocol_Version min_version() const;
+
+ /**
+ * @return the version we would prefer to negotiate
+ */
+ virtual Protocol_Version pref_version() const;
+
+ virtual ~Policy() {}
+ };
+
+/**
+* Return allowed ciphersuites, in order of preference
+*/
+std::vector<u16bit> ciphersuite_list(const Policy& policy,
+ bool have_srp);
+
+}
+
+}
+
+#endif
diff --git a/src/ssl/tls_reader.h b/src/tls/tls_reader.h
index 3a45235b5..7440e16b7 100644
--- a/src/ssl/tls_reader.h
+++ b/src/tls/tls_reader.h
@@ -1,6 +1,6 @@
/*
* TLS Data Reader
-* (C) 2010 Jack Lloyd
+* (C) 2010-2011 Jack Lloyd
*
* Released under the terms of the Botan license
*/
@@ -8,20 +8,32 @@
#ifndef BOTAN_TLS_READER_H__
#define BOTAN_TLS_READER_H__
+#include <botan/exceptn.h>
#include <botan/secmem.h>
#include <botan/loadstor.h>
+#include <string>
+#include <vector>
+#include <stdexcept>
namespace Botan {
+namespace TLS {
+
/**
* Helper class for decoding TLS protocol messages
*/
class TLS_Data_Reader
{
public:
- TLS_Data_Reader(const MemoryRegion<byte>& buf_in) :
+ TLS_Data_Reader(const std::vector<byte>& buf_in) :
buf(buf_in), offset(0) {}
+ void assert_done() const
+ {
+ if(has_remaining())
+ throw Decoding_Error("Extra bytes at end of message");
+ }
+
size_t remaining_bytes() const
{
return buf.size() - offset;
@@ -38,6 +50,15 @@ class TLS_Data_Reader
offset += bytes;
}
+ u16bit get_u32bit()
+ {
+ assert_at_least(4);
+ u16bit result = make_u32bit(buf[offset ], buf[offset+1],
+ buf[offset+2], buf[offset+3]);
+ offset += 4;
+ return result;
+ }
+
u16bit get_u16bit()
{
assert_at_least(2);
@@ -70,14 +91,14 @@ class TLS_Data_Reader
}
template<typename T>
- SecureVector<T> get_range(size_t len_bytes,
+ std::vector<T> get_range(size_t len_bytes,
size_t min_elems,
size_t max_elems)
{
const size_t num_elems =
get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
- return get_elem<T, SecureVector<T> >(num_elems);
+ return get_elem<T, std::vector<T> >(num_elems);
}
template<typename T>
@@ -91,10 +112,20 @@ class TLS_Data_Reader
return get_elem<T, std::vector<T> >(num_elems);
}
+ std::string get_string(size_t len_bytes,
+ size_t min_bytes,
+ size_t max_bytes)
+ {
+ std::vector<byte> v =
+ get_range_vector<byte>(len_bytes, min_bytes, max_bytes);
+
+ return std::string(reinterpret_cast<char*>(&v[0]), v.size());
+ }
+
template<typename T>
- SecureVector<T> get_fixed(size_t size)
+ std::vector<T> get_fixed(size_t size)
{
- return get_elem<T, SecureVector<T> >(size);
+ return get_elem<T, std::vector<T> >(size);
}
private:
@@ -131,18 +162,22 @@ class TLS_Data_Reader
void assert_at_least(size_t n) const
{
if(buf.size() - offset < n)
- throw Decoding_Error("TLS_Data_Reader: Corrupt packet");
+ {
+ throw Decoding_Error("TLS_Data_Reader: Expected " + std::to_string(n) +
+ " bytes remaining, only " + std::to_string(buf.size()-offset) +
+ " left");
+ }
}
- const MemoryRegion<byte>& buf;
+ const std::vector<byte>& buf;
size_t offset;
};
/**
* Helper function for encoding length-tagged vectors
*/
-template<typename T>
-void append_tls_length_value(MemoryRegion<byte>& buf,
+template<typename T, typename Alloc>
+void append_tls_length_value(std::vector<byte, Alloc>& buf,
const T* vals,
size_t vals_size,
size_t tag_size)
@@ -165,22 +200,27 @@ void append_tls_length_value(MemoryRegion<byte>& buf,
buf.push_back(get_byte(j, vals[i]));
}
-template<typename T>
-void append_tls_length_value(MemoryRegion<byte>& buf,
- const MemoryRegion<T>& vals,
+template<typename T, typename Alloc, typename Alloc2>
+void append_tls_length_value(std::vector<byte, Alloc>& buf,
+ const std::vector<T, Alloc2>& vals,
size_t tag_size)
{
append_tls_length_value(buf, &vals[0], vals.size(), tag_size);
}
-template<typename T>
-void append_tls_length_value(MemoryRegion<byte>& buf,
- const std::vector<T>& vals,
+template<typename Alloc>
+void append_tls_length_value(std::vector<byte, Alloc>& buf,
+ const std::string& str,
size_t tag_size)
{
- append_tls_length_value(buf, &vals[0], vals.size(), tag_size);
+ append_tls_length_value(buf,
+ reinterpret_cast<const byte*>(&str[0]),
+ str.size(),
+ tag_size);
}
}
+}
+
#endif
diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h
new file mode 100644
index 000000000..a92dcbe9d
--- /dev/null
+++ b/src/tls/tls_record.h
@@ -0,0 +1,136 @@
+/*
+* TLS Record Handling
+* (C) 2004-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_RECORDS_H__
+#define BOTAN_TLS_RECORDS_H__
+
+#include <botan/tls_ciphersuite.h>
+#include <botan/tls_alert.h>
+#include <botan/tls_magic.h>
+#include <botan/tls_version.h>
+#include <botan/pipe.h>
+#include <botan/mac.h>
+#include <botan/secqueue.h>
+#include <vector>
+#include <functional>
+
+namespace Botan {
+
+namespace TLS {
+
+class Session_Keys;
+
+/**
+* TLS Record Writer
+*/
+class BOTAN_DLL Record_Writer
+ {
+ public:
+ void send(byte type, const byte input[], size_t length);
+ void send(byte type, byte val) { send(type, &val, 1); }
+
+ void send(byte type, const std::vector<byte>& input)
+ { send(type, &input[0], input.size()); }
+
+ std::vector<byte> send(class Handshake_Message& msg);
+
+ void send_alert(const Alert& alert);
+
+ void activate(Connection_Side side,
+ const Ciphersuite& suite,
+ const Session_Keys& keys,
+ byte compression_method);
+
+ void set_version(Protocol_Version version);
+
+ void reset();
+
+ void set_maximum_fragment_size(size_t max_fragment);
+
+ Record_Writer(std::function<void (const byte[], size_t)> output_fn);
+
+ ~Record_Writer() { delete m_mac; }
+ private:
+ Record_Writer(const Record_Writer&) {}
+ Record_Writer& operator=(const Record_Writer&) { return (*this); }
+
+ void send_record(byte type, const byte input[], size_t length);
+
+ std::function<void (const byte[], size_t)> m_output_fn;
+
+ std::vector<byte> m_writebuf;
+
+ Pipe m_cipher;
+ MessageAuthenticationCode* m_mac;
+
+ size_t m_block_size, m_mac_size, m_iv_size, m_max_fragment;
+
+ u64bit m_seq_no;
+ Protocol_Version m_version;
+ };
+
+/**
+* TLS Record Reader
+*/
+class BOTAN_DLL Record_Reader
+ {
+ public:
+
+ /**
+ * @param input new input data (may be NULL if input_size == 0)
+ * @param input_size size of input in bytes
+ * @param input_consumed is set to the number of bytes of input
+ * that were consumed
+ * @param msg_type is set to the type of the message just read if
+ * this function returns 0
+ * @param msg is set to the contents of the record
+ * @return number of bytes still needed (minimum), or 0 if success
+ */
+ size_t add_input(const byte input[], size_t input_size,
+ size_t& input_consumed,
+ byte& msg_type,
+ std::vector<byte>& msg);
+
+ void activate(Connection_Side side,
+ const Ciphersuite& suite,
+ const Session_Keys& keys,
+ byte compression_method);
+
+ void set_version(Protocol_Version version);
+
+ void reset();
+
+ void set_maximum_fragment_size(size_t max_fragment);
+
+ Record_Reader();
+
+ ~Record_Reader() { delete m_mac; }
+ private:
+ Record_Reader(const Record_Reader&) {}
+ Record_Reader& operator=(const Record_Reader&) { return (*this); }
+
+ size_t fill_buffer_to(const byte*& input,
+ size_t& input_size,
+ size_t& input_consumed,
+ size_t desired);
+
+ std::vector<byte> m_readbuf;
+ std::vector<byte> m_macbuf;
+ size_t m_readbuf_pos;
+
+ Pipe m_cipher;
+ MessageAuthenticationCode* m_mac;
+ size_t m_block_size, m_iv_size, m_max_fragment;
+ u64bit m_seq_no;
+ Protocol_Version m_version;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
new file mode 100644
index 000000000..241215d59
--- /dev/null
+++ b/src/tls/tls_server.cpp
@@ -0,0 +1,620 @@
+/*
+* TLS Server
+* (C) 2004-2011,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_server.h>
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/stl_util.h>
+#include <botan/internal/assert.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+bool check_for_resume(Session& session_info,
+ Session_Manager& session_manager,
+ Credentials_Manager& credentials,
+ Client_Hello* client_hello,
+ std::chrono::seconds session_ticket_lifetime)
+ {
+ const std::vector<byte>& client_session_id = client_hello->session_id();
+ const std::vector<byte>& session_ticket = client_hello->session_ticket();
+
+ if(session_ticket.empty())
+ {
+ if(client_session_id.empty()) // not resuming
+ return false;
+
+ // not found
+ if(!session_manager.load_from_session_id(client_session_id, session_info))
+ return false;
+ }
+ else
+ {
+ // If a session ticket was sent, ignore client session ID
+ try
+ {
+ session_info = Session::decrypt(
+ session_ticket,
+ credentials.psk("tls-server", "session-ticket", ""));
+
+ if(session_ticket_lifetime != std::chrono::seconds(0) &&
+ session_info.session_age() > session_ticket_lifetime)
+ return false; // ticket has expired
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+ // wrong version
+ if(client_hello->version() != session_info.version())
+ return false;
+
+ // client didn't send original ciphersuite
+ if(!value_exists(client_hello->ciphersuites(),
+ session_info.ciphersuite_code()))
+ return false;
+
+ // client didn't send original compression method
+ if(!value_exists(client_hello->compression_methods(),
+ session_info.compression_method()))
+ return false;
+
+ // client sent a different SRP identity
+ if(client_hello->srp_identifier() != "")
+ {
+ if(client_hello->srp_identifier() != session_info.srp_identifier())
+ return false;
+ }
+
+ // client sent a different SNI hostname
+ if(client_hello->sni_hostname() != "")
+ {
+ if(client_hello->sni_hostname() != session_info.sni_hostname())
+ return false;
+ }
+
+ return true;
+ }
+
+/*
+* Choose which ciphersuite to use
+*/
+u16bit choose_ciphersuite(
+ const Policy& policy,
+ Credentials_Manager& creds,
+ const std::map<std::string, std::vector<X509_Certificate> >& cert_chains,
+ const Client_Hello* client_hello)
+ {
+ const bool have_srp = creds.attempt_srp("tls-server",
+ client_hello->sni_hostname());
+
+ const std::vector<u16bit> client_suites = client_hello->ciphersuites();
+ const std::vector<u16bit> server_suites = ciphersuite_list(policy, have_srp);
+
+ if(server_suites.empty())
+ throw Internal_Error("Policy forbids us from negotiating any ciphersuite");
+
+ const bool have_shared_ecc_curve =
+ (policy.choose_curve(client_hello->supported_ecc_curves()) != "");
+
+ // Ordering by our preferences rather than by clients
+ for(size_t i = 0; i != server_suites.size(); ++i)
+ {
+ const u16bit suite_id = server_suites[i];
+
+ if(!value_exists(client_suites, suite_id))
+ continue;
+
+ Ciphersuite suite = Ciphersuite::by_id(suite_id);
+
+ if(!have_shared_ecc_curve && suite.ecc_ciphersuite())
+ continue;
+
+ if(cert_chains.count(suite.sig_algo()) == 0)
+ continue;
+
+ /*
+ The client may offer SRP cipher suites in the hello message but
+ omit the SRP extension. If the server would like to select an
+ SRP cipher suite in this case, the server SHOULD return a fatal
+ "unknown_psk_identity" alert immediately after processing the
+ client hello message.
+ - RFC 5054 section 2.5.1.2
+ */
+ if(suite.kex_algo() == "SRP_SHA" && client_hello->srp_identifier() == "")
+ throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
+ "Client wanted SRP but did not send username");
+
+ return suite_id;
+ }
+
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Can't agree on a ciphersuite with client");
+ }
+
+
+/*
+* Choose which compression algorithm to use
+*/
+byte choose_compression(const Policy& policy,
+ const std::vector<byte>& c_comp)
+ {
+ std::vector<byte> s_comp = policy.compression();
+
+ for(size_t i = 0; i != s_comp.size(); ++i)
+ for(size_t j = 0; j != c_comp.size(); ++j)
+ if(s_comp[i] == c_comp[j])
+ return s_comp[i];
+
+ return NO_COMPRESSION;
+ }
+
+std::map<std::string, std::vector<X509_Certificate> >
+get_server_certs(const std::string& hostname,
+ Credentials_Manager& creds)
+ {
+ const char* cert_types[] = { "RSA", "DSA", "ECDSA", nullptr };
+
+ std::map<std::string, std::vector<X509_Certificate> > cert_chains;
+
+ for(size_t i = 0; cert_types[i]; ++i)
+ {
+ std::vector<X509_Certificate> certs =
+ creds.cert_chain_single_type(cert_types[i], "tls-server", hostname);
+
+ if(!certs.empty())
+ cert_chains[cert_types[i]] = certs;
+ }
+
+ return cert_chains;
+ }
+
+}
+
+/*
+* TLS Server Constructor
+*/
+Server::Server(std::function<void (const byte[], size_t)> output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_fn,
+ Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& next_protocols) :
+ Channel(output_fn, proc_fn, handshake_fn),
+ policy(policy),
+ rng(rng),
+ session_manager(session_manager),
+ creds(creds),
+ m_possible_protocols(next_protocols)
+ {
+ }
+
+/*
+* Send a hello request to the client
+*/
+void Server::renegotiate(bool force_full_renegotiation)
+ {
+ if(state)
+ return; // currently in handshake
+
+ state = new Handshake_State(new Stream_Handshake_Reader);
+
+ state->allow_session_resumption = !force_full_renegotiation;
+ state->set_expected_next(CLIENT_HELLO);
+ Hello_Request hello_req(writer);
+ }
+
+void Server::alert_notify(const Alert& alert)
+ {
+ if(alert.type() == Alert::NO_RENEGOTIATION)
+ {
+ if(handshake_completed && state)
+ {
+ delete state;
+ state = nullptr;
+ }
+ }
+ }
+
+/*
+* Split up and process handshake messages
+*/
+void Server::read_handshake(byte rec_type,
+ const std::vector<byte>& rec_buf)
+ {
+ if(rec_type == HANDSHAKE && !state)
+ {
+ state = new Handshake_State(new Stream_Handshake_Reader);
+ state->set_expected_next(CLIENT_HELLO);
+ }
+
+ Channel::read_handshake(rec_type, rec_buf);
+ }
+
+/*
+* Process a handshake message
+*/
+void Server::process_handshake_msg(Handshake_Type type,
+ const std::vector<byte>& contents)
+ {
+ if(!state)
+ throw Unexpected_Message("Unexpected handshake message from client");
+
+ state->confirm_transition_to(type);
+
+ /*
+ * The change cipher spec message isn't technically a handshake
+ * message so it's not included in the hash. The finished and
+ * certificate verify messages are verified based on the current
+ * state of the hash *before* this message so we delay adding them
+ * to the hash computation until we've processed them below.
+ */
+ if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY)
+ {
+ if(type == CLIENT_HELLO_SSLV2)
+ state->hash.update(contents);
+ else
+ state->hash.update(type, contents);
+ }
+
+ if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
+ {
+ state->client_hello = new Client_Hello(contents, type);
+
+ if(state->client_hello->sni_hostname() != "")
+ m_hostname = state->client_hello->sni_hostname();
+
+ Protocol_Version client_version = state->client_hello->version();
+
+ if(client_version < policy.min_version())
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Client version is unacceptable by policy");
+
+ if(client_version <= policy.pref_version())
+ state->set_version(client_version);
+ else
+ state->set_version(policy.pref_version());
+
+ secure_renegotiation.update(state->client_hello);
+
+ m_peer_supports_heartbeats = state->client_hello->supports_heartbeats();
+ m_heartbeat_sending_allowed = state->client_hello->peer_can_send_heartbeats();
+
+ writer.set_version(state->version());
+ reader.set_version(state->version());
+
+ Session session_info;
+ const bool resuming =
+ state->allow_session_resumption &&
+ check_for_resume(session_info,
+ session_manager,
+ creds,
+ state->client_hello,
+ std::chrono::seconds(policy.session_ticket_lifetime()));
+
+ bool have_session_ticket_key = false;
+
+ try
+ {
+ have_session_ticket_key =
+ creds.psk("tls-server", "session-ticket", "").length() > 0;
+ }
+ catch(...) {}
+
+ if(resuming)
+ {
+ // resume session
+
+ state->server_hello = new Server_Hello(
+ writer,
+ state->hash,
+ state->client_hello->session_id(),
+ Protocol_Version(session_info.version()),
+ session_info.ciphersuite_code(),
+ session_info.compression_method(),
+ session_info.fragment_size(),
+ secure_renegotiation.supported(),
+ secure_renegotiation.for_server_hello(),
+ (state->client_hello->supports_session_ticket() &&
+ state->client_hello->session_ticket().empty() &&
+ have_session_ticket_key),
+ state->client_hello->next_protocol_notification(),
+ m_possible_protocols,
+ state->client_hello->supports_heartbeats(),
+ rng);
+
+ secure_renegotiation.update(state->server_hello);
+
+ if(session_info.fragment_size())
+ {
+ reader.set_maximum_fragment_size(session_info.fragment_size());
+ writer.set_maximum_fragment_size(session_info.fragment_size());
+ }
+
+ state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());
+
+ state->keys = Session_Keys(state, session_info.master_secret(), true);
+
+ if(!handshake_fn(session_info))
+ {
+ session_manager.remove_entry(session_info.session_id());
+
+ if(state->server_hello->supports_session_ticket()) // send an empty ticket
+ state->new_session_ticket = new New_Session_Ticket(writer, state->hash);
+ }
+
+ if(state->server_hello->supports_session_ticket() && !state->new_session_ticket)
+ {
+ try
+ {
+ const SymmetricKey ticket_key = creds.psk("tls-server", "session-ticket", "");
+
+ state->new_session_ticket =
+ new New_Session_Ticket(writer, state->hash,
+ session_info.encrypt(ticket_key, rng),
+ policy.session_ticket_lifetime());
+ }
+ catch(...) {}
+
+ if(!state->new_session_ticket)
+ state->new_session_ticket = new New_Session_Ticket(writer, state->hash);
+ }
+
+ writer.send(CHANGE_CIPHER_SPEC, 1);
+
+ writer.activate(SERVER, state->suite, state->keys,
+ state->server_hello->compression_method());
+
+ state->server_finished = new Finished(writer, state, SERVER);
+
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else // new session
+ {
+ std::map<std::string, std::vector<X509_Certificate> > cert_chains;
+
+ cert_chains = get_server_certs(m_hostname, creds);
+
+ if(m_hostname != "" && cert_chains.empty())
+ {
+ send_alert(Alert(Alert::UNRECOGNIZED_NAME));
+ cert_chains = get_server_certs("", creds);
+ }
+
+ state->server_hello = new Server_Hello(
+ writer,
+ state->hash,
+ unlock(rng.random_vec(32)), // new session ID
+ state->version(),
+ choose_ciphersuite(policy, creds, cert_chains, state->client_hello),
+ choose_compression(policy, state->client_hello->compression_methods()),
+ state->client_hello->fragment_size(),
+ secure_renegotiation.supported(),
+ secure_renegotiation.for_server_hello(),
+ state->client_hello->supports_session_ticket() && have_session_ticket_key,
+ state->client_hello->next_protocol_notification(),
+ m_possible_protocols,
+ state->client_hello->supports_heartbeats(),
+ rng);
+
+ secure_renegotiation.update(state->server_hello);
+
+ if(state->client_hello->fragment_size())
+ {
+ reader.set_maximum_fragment_size(state->client_hello->fragment_size());
+ writer.set_maximum_fragment_size(state->client_hello->fragment_size());
+ }
+
+ state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());
+
+ const std::string sig_algo = state->suite.sig_algo();
+ const std::string kex_algo = state->suite.kex_algo();
+
+ if(sig_algo != "")
+ {
+ BOTAN_ASSERT(!cert_chains[sig_algo].empty(),
+ "Attempting to send empty certificate chain");
+
+ state->server_certs = new Certificate(writer,
+ state->hash,
+ cert_chains[sig_algo]);
+ }
+
+ Private_Key* private_key = nullptr;
+
+ if(kex_algo == "RSA" || sig_algo != "")
+ {
+ private_key = creds.private_key_for(state->server_certs->cert_chain()[0],
+ "tls-server",
+ m_hostname);
+
+ if(!private_key)
+ throw Internal_Error("No private key located for associated server cert");
+ }
+
+ if(kex_algo == "RSA")
+ {
+ state->server_rsa_kex_key = private_key;
+ }
+ else
+ {
+ state->server_kex =
+ new Server_Key_Exchange(writer, state, policy, creds, rng, private_key);
+ }
+
+ std::vector<X509_Certificate> client_auth_CAs =
+ creds.trusted_certificate_authorities("tls-server", m_hostname);
+
+ if(!client_auth_CAs.empty() && state->suite.sig_algo() != "")
+ {
+ state->cert_req = new Certificate_Req(writer,
+ state->hash,
+ policy,
+ client_auth_CAs,
+ state->version());
+
+ state->set_expected_next(CERTIFICATE);
+ }
+
+ /*
+ * If the client doesn't have a cert they want to use they are
+ * allowed to send either an empty cert message or proceed
+ * directly to the client key exchange, so allow either case.
+ */
+ state->set_expected_next(CLIENT_KEX);
+
+ state->server_hello_done = new Server_Hello_Done(writer, state->hash);
+ }
+ }
+ else if(type == CERTIFICATE)
+ {
+ state->client_certs = new Certificate(contents);
+
+ state->set_expected_next(CLIENT_KEX);
+ }
+ else if(type == CLIENT_KEX)
+ {
+ if(state->received_handshake_msg(CERTIFICATE) && !state->client_certs->empty())
+ state->set_expected_next(CERTIFICATE_VERIFY);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
+
+ state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng);
+
+ state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false);
+ }
+ else if(type == CERTIFICATE_VERIFY)
+ {
+ state->client_verify = new Certificate_Verify(contents, state->version());
+
+ peer_certs = state->client_certs->cert_chain();
+
+ const bool sig_valid =
+ state->client_verify->verify(peer_certs[0], state);
+
+ state->hash.update(type, contents);
+
+ /*
+ * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
+ * "A handshake cryptographic operation failed, including being
+ * unable to correctly verify a signature, ..."
+ */
+ if(!sig_valid)
+ throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed");
+
+ try
+ {
+ creds.verify_certificate_chain("tls-server", "", peer_certs);
+ }
+ catch(std::exception& e)
+ {
+ throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
+ }
+
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else if(type == HANDSHAKE_CCS)
+ {
+ if(state->server_hello->next_protocol_notification())
+ state->set_expected_next(NEXT_PROTOCOL);
+ else
+ state->set_expected_next(FINISHED);
+
+ reader.activate(SERVER, state->suite, state->keys,
+ state->server_hello->compression_method());
+ }
+ else if(type == NEXT_PROTOCOL)
+ {
+ state->set_expected_next(FINISHED);
+
+ state->next_protocol = new Next_Protocol(contents);
+
+ m_next_protocol = state->next_protocol->protocol();
+ }
+ else if(type == FINISHED)
+ {
+ state->set_expected_next(HANDSHAKE_NONE);
+
+ state->client_finished = new Finished(contents);
+
+ if(!state->client_finished->verify(state, CLIENT))
+ throw TLS_Exception(Alert::DECRYPT_ERROR,
+ "Finished message didn't verify");
+
+ if(!state->server_finished)
+ {
+ // already sent finished if resuming, so this is a new session
+
+ state->hash.update(type, contents);
+
+ Session session_info(
+ state->server_hello->session_id(),
+ state->keys.master_secret(),
+ state->server_hello->version(),
+ state->server_hello->ciphersuite(),
+ state->server_hello->compression_method(),
+ SERVER,
+ secure_renegotiation.supported(),
+ state->server_hello->fragment_size(),
+ peer_certs,
+ std::vector<byte>(),
+ m_hostname,
+ state->srp_identifier()
+ );
+
+ if(handshake_fn(session_info))
+ {
+ if(state->server_hello->supports_session_ticket())
+ {
+ try
+ {
+ const SymmetricKey ticket_key = creds.psk("tls-server", "session-ticket", "");
+
+ state->new_session_ticket =
+ new New_Session_Ticket(writer, state->hash,
+ session_info.encrypt(ticket_key, rng),
+ policy.session_ticket_lifetime());
+ }
+ catch(...) {}
+ }
+ else
+ session_manager.save(session_info);
+ }
+
+ if(state->server_hello->supports_session_ticket() && !state->new_session_ticket)
+ state->new_session_ticket = new New_Session_Ticket(writer, state->hash);
+
+ writer.send(CHANGE_CIPHER_SPEC, 1);
+
+ writer.activate(SERVER, state->suite, state->keys,
+ state->server_hello->compression_method());
+
+ state->server_finished = new Finished(writer, state, SERVER);
+ }
+
+ secure_renegotiation.update(state->client_finished,
+ state->server_finished);
+
+ delete state;
+ state = nullptr;
+ handshake_completed = true;
+ }
+ else
+ throw Unexpected_Message("Unknown handshake message received");
+ }
+
+}
+
+}
diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h
new file mode 100644
index 000000000..441e03eb2
--- /dev/null
+++ b/src/tls/tls_server.h
@@ -0,0 +1,74 @@
+/*
+* TLS Server
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_SERVER_H__
+#define BOTAN_TLS_SERVER_H__
+
+#include <botan/tls_channel.h>
+#include <botan/tls_session_manager.h>
+#include <botan/credentials_manager.h>
+#include <vector>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* TLS Server
+*/
+class BOTAN_DLL Server : public Channel
+ {
+ public:
+ /**
+ * Server initialization
+ */
+ Server(std::function<void (const byte[], size_t)> socket_output_fn,
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_complete,
+ Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& protocols =
+ std::vector<std::string>());
+
+ void renegotiate(bool force_full_renegotiation);
+
+ /**
+ * Return the server name indicator, if sent by the client
+ */
+ std::string server_name_indicator() const
+ { return m_hostname; }
+
+ /**
+ * Return the protocol negotiated with NPN extension
+ */
+ std::string next_protocol() const
+ { return m_next_protocol; }
+
+ private:
+ void read_handshake(byte, const std::vector<byte>&);
+
+ void process_handshake_msg(Handshake_Type, const std::vector<byte>&);
+
+ void alert_notify(const Alert& alert);
+
+ const Policy& policy;
+ RandomNumberGenerator& rng;
+ Session_Manager& session_manager;
+ Credentials_Manager& creds;
+
+ std::vector<std::string> m_possible_protocols;
+ std::string m_hostname;
+ std::string m_next_protocol;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp
new file mode 100644
index 000000000..d2aae9a7e
--- /dev/null
+++ b/src/tls/tls_session.cpp
@@ -0,0 +1,251 @@
+/*
+* TLS Session State
+* (C) 2011-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_session.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_str.h>
+#include <botan/pem.h>
+#include <botan/lookup.h>
+#include <botan/loadstor.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+Session::Session(const std::vector<byte>& session_identifier,
+ const secure_vector<byte>& master_secret,
+ Protocol_Version version,
+ u16bit ciphersuite,
+ byte compression_method,
+ Connection_Side side,
+ bool secure_renegotiation_supported,
+ size_t fragment_size,
+ const std::vector<X509_Certificate>& certs,
+ const std::vector<byte>& ticket,
+ const std::string& sni_hostname,
+ const std::string& srp_identifier) :
+ m_start_time(std::chrono::system_clock::now()),
+ m_identifier(session_identifier),
+ m_session_ticket(ticket),
+ m_master_secret(master_secret),
+ m_version(version),
+ m_ciphersuite(ciphersuite),
+ m_compression_method(compression_method),
+ m_connection_side(side),
+ m_secure_renegotiation_supported(secure_renegotiation_supported),
+ m_fragment_size(fragment_size),
+ m_peer_certs(certs),
+ m_sni_hostname(sni_hostname),
+ m_srp_identifier(srp_identifier)
+ {
+ }
+
+Session::Session(const std::string& pem)
+ {
+ secure_vector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION");
+
+ *this = Session(&der[0], der.size());
+ }
+
+Session::Session(const byte ber[], size_t ber_len)
+ {
+ byte side_code = 0;
+ ASN1_String sni_hostname_str;
+ ASN1_String srp_identifier_str;
+
+ byte major_version = 0, minor_version = 0;
+
+ std::vector<byte> peer_cert_bits;
+
+ size_t start_time = 0;
+
+ BER_Decoder(ber, ber_len)
+ .start_cons(SEQUENCE)
+ .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
+ "Unknown version in session structure")
+ .decode_integer_type(start_time)
+ .decode_integer_type(major_version)
+ .decode_integer_type(minor_version)
+ .decode(m_identifier, OCTET_STRING)
+ .decode(m_session_ticket, OCTET_STRING)
+ .decode_integer_type(m_ciphersuite)
+ .decode_integer_type(m_compression_method)
+ .decode_integer_type(side_code)
+ .decode_integer_type(m_fragment_size)
+ .decode(m_secure_renegotiation_supported)
+ .decode(m_master_secret, OCTET_STRING)
+ .decode(peer_cert_bits, OCTET_STRING)
+ .decode(sni_hostname_str)
+ .decode(srp_identifier_str)
+ .end_cons()
+ .verify_end();
+
+ m_version = Protocol_Version(major_version, minor_version);
+ m_start_time = std::chrono::system_clock::from_time_t(start_time);
+ m_sni_hostname = sni_hostname_str.value();
+ m_srp_identifier = srp_identifier_str.value();
+ m_connection_side = static_cast<Connection_Side>(side_code);
+
+ if(!peer_cert_bits.empty())
+ {
+ DataSource_Memory certs(&peer_cert_bits[0], peer_cert_bits.size());
+
+ while(!certs.end_of_data())
+ m_peer_certs.push_back(X509_Certificate(certs));
+ }
+ }
+
+secure_vector<byte> Session::DER_encode() const
+ {
+ std::vector<byte> peer_cert_bits;
+ for(size_t i = 0; i != m_peer_certs.size(); ++i)
+ peer_cert_bits += m_peer_certs[i].BER_encode();
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
+ .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
+ .encode(static_cast<size_t>(m_version.major_version()))
+ .encode(static_cast<size_t>(m_version.minor_version()))
+ .encode(m_identifier, OCTET_STRING)
+ .encode(m_session_ticket, OCTET_STRING)
+ .encode(static_cast<size_t>(m_ciphersuite))
+ .encode(static_cast<size_t>(m_compression_method))
+ .encode(static_cast<size_t>(m_connection_side))
+ .encode(static_cast<size_t>(m_fragment_size))
+ .encode(m_secure_renegotiation_supported)
+ .encode(m_master_secret, OCTET_STRING)
+ .encode(peer_cert_bits, OCTET_STRING)
+ .encode(ASN1_String(m_sni_hostname, UTF8_STRING))
+ .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
+ .end_cons()
+ .get_contents();
+ }
+
+std::string Session::PEM_encode() const
+ {
+ return PEM_Code::encode(this->DER_encode(), "SSL SESSION");
+ }
+
+std::chrono::seconds Session::session_age() const
+ {
+ return std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now() - m_start_time);
+ }
+
+namespace {
+
+const u32bit SESSION_CRYPTO_MAGIC = 0x571B0E4E;
+const std::string SESSION_CRYPTO_CIPHER = "AES-256/CBC";
+const std::string SESSION_CRYPTO_MAC = "HMAC(SHA-256)";
+const std::string SESSION_CRYPTO_KDF = "KDF2(SHA-256)";
+
+const size_t MAGIC_LENGTH = 4;
+const size_t MAC_KEY_LENGTH = 32;
+const size_t CIPHER_KEY_LENGTH = 32;
+const size_t CIPHER_IV_LENGTH = 16;
+const size_t MAC_OUTPUT_LENGTH = 32;
+
+}
+
+std::vector<byte>
+Session::encrypt(const SymmetricKey& master_key,
+ RandomNumberGenerator& rng) const
+ {
+ std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF));
+
+ SymmetricKey cipher_key =
+ kdf->derive_key(CIPHER_KEY_LENGTH,
+ master_key.bits_of(),
+ "tls.session.cipher-key");
+
+ SymmetricKey mac_key =
+ kdf->derive_key(MAC_KEY_LENGTH,
+ master_key.bits_of(),
+ "tls.session.mac-key");
+
+ InitializationVector cipher_iv(rng, 16);
+
+ std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC));
+ mac->set_key(mac_key);
+
+ Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, ENCRYPTION));
+ pipe.process_msg(this->DER_encode());
+ secure_vector<byte> ctext = pipe.read_all(0);
+
+ std::vector<byte> out(MAGIC_LENGTH);
+ store_be(SESSION_CRYPTO_MAGIC, &out[0]);
+ out += cipher_iv.bits_of();
+ out += ctext;
+
+ mac->update(out);
+
+ out += mac->final();
+ return out;
+ }
+
+Session Session::decrypt(const byte buf[], size_t buf_len,
+ const SymmetricKey& master_key)
+ {
+ try
+ {
+ const size_t MIN_CTEXT_SIZE = 4 * 16; // due to 48 byte master secret
+
+ if(buf_len < (MAGIC_LENGTH +
+ CIPHER_IV_LENGTH +
+ MIN_CTEXT_SIZE +
+ MAC_OUTPUT_LENGTH))
+ throw Decoding_Error("Encrypted TLS session too short to be valid");
+
+ if(load_be<u32bit>(buf, 0) != SESSION_CRYPTO_MAGIC)
+ throw Decoding_Error("Unknown header value in encrypted session");
+
+ std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF));
+
+ SymmetricKey mac_key =
+ kdf->derive_key(MAC_KEY_LENGTH,
+ master_key.bits_of(),
+ "tls.session.mac-key");
+
+ std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC));
+ mac->set_key(mac_key);
+
+ mac->update(&buf[0], buf_len - MAC_OUTPUT_LENGTH);
+ secure_vector<byte> computed_mac = mac->final();
+
+ if(!same_mem(&buf[buf_len - MAC_OUTPUT_LENGTH], &computed_mac[0], computed_mac.size()))
+ throw Decoding_Error("MAC verification failed for encrypted session");
+
+ SymmetricKey cipher_key =
+ kdf->derive_key(CIPHER_KEY_LENGTH,
+ master_key.bits_of(),
+ "tls.session.cipher-key");
+
+ InitializationVector cipher_iv(&buf[MAGIC_LENGTH], CIPHER_IV_LENGTH);
+
+ const size_t CTEXT_OFFSET = MAGIC_LENGTH + CIPHER_IV_LENGTH;
+
+ Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, DECRYPTION));
+ pipe.process_msg(&buf[CTEXT_OFFSET],
+ buf_len - (MAC_OUTPUT_LENGTH + CTEXT_OFFSET));
+ secure_vector<byte> ber = pipe.read_all();
+
+ return Session(&ber[0], ber.size());
+ }
+ catch(std::exception& e)
+ {
+ throw Decoding_Error("Failed to decrypt encrypted session -" +
+ std::string(e.what()));
+ }
+ }
+
+}
+
+}
+
diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h
new file mode 100644
index 000000000..2c474bc6a
--- /dev/null
+++ b/src/tls/tls_session.h
@@ -0,0 +1,217 @@
+/*
+* TLS Session
+* (C) 2011-2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_SESSION_STATE_H__
+#define BOTAN_TLS_SESSION_STATE_H__
+
+#include <botan/x509cert.h>
+#include <botan/tls_version.h>
+#include <botan/tls_ciphersuite.h>
+#include <botan/tls_magic.h>
+#include <botan/secmem.h>
+#include <botan/symkey.h>
+#include <chrono>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Class representing a TLS session state
+*/
+class BOTAN_DLL Session
+ {
+ public:
+
+ /**
+ * Uninitialized session
+ */
+ Session() :
+ m_start_time(std::chrono::system_clock::time_point::min()),
+ m_version(),
+ m_ciphersuite(0),
+ m_compression_method(0),
+ m_connection_side(static_cast<Connection_Side>(0)),
+ m_secure_renegotiation_supported(false),
+ m_fragment_size(0)
+ {}
+
+ /**
+ * New session (sets session start time)
+ */
+ Session(const std::vector<byte>& session_id,
+ const secure_vector<byte>& master_secret,
+ Protocol_Version version,
+ u16bit ciphersuite,
+ byte compression_method,
+ Connection_Side side,
+ bool secure_renegotiation_supported,
+ size_t fragment_size,
+ const std::vector<X509_Certificate>& peer_certs,
+ const std::vector<byte>& session_ticket,
+ const std::string& sni_hostname = "",
+ const std::string& srp_identifier = "");
+
+ /**
+ * Load a session from DER representation (created by DER_encode)
+ */
+ Session(const byte ber[], size_t ber_len);
+
+ /**
+ * Load a session from PEM representation (created by PEM_encode)
+ */
+ Session(const std::string& pem);
+
+ /**
+ * Encode this session data for storage
+ * @warning if the master secret is compromised so is the
+ * session traffic
+ */
+ secure_vector<byte> DER_encode() const;
+
+ /**
+ * Encrypt a session (useful for serialization or session tickets)
+ */
+ std::vector<byte> encrypt(const SymmetricKey& key,
+ RandomNumberGenerator& rng) const;
+
+
+ /**
+ * Decrypt a session created by encrypt
+ * @param ctext the ciphertext returned by encrypt
+ * @param ctext_size the size of ctext in bytes
+ * @param key the same key used by the encrypting side
+ */
+ static Session decrypt(const byte ctext[],
+ size_t ctext_size,
+ const SymmetricKey& key);
+
+ /**
+ * Decrypt a session created by encrypt
+ * @param ctext the ciphertext returned by encrypt
+ * @param key the same key used by the encrypting side
+ */
+ static inline Session decrypt(const std::vector<byte>& ctext,
+ const SymmetricKey& key)
+ {
+ return Session::decrypt(&ctext[0], ctext.size(), key);
+ }
+
+ /**
+ * Encode this session data for storage
+ * @warning if the master secret is compromised so is the
+ * session traffic
+ */
+ std::string PEM_encode() const;
+
+ /**
+ * Get the version of the saved session
+ */
+ Protocol_Version version() const { return m_version; }
+
+ /**
+ * Get the ciphersuite code of the saved session
+ */
+ u16bit ciphersuite_code() const { return m_ciphersuite; }
+
+ /**
+ * Get the ciphersuite info of the saved session
+ */
+ Ciphersuite ciphersuite() const { return Ciphersuite::by_id(m_ciphersuite); }
+
+ /**
+ * Get the compression method used in the saved session
+ */
+ byte compression_method() const { return m_compression_method; }
+
+ /**
+ * Get which side of the connection the resumed session we are/were
+ * acting as.
+ */
+ Connection_Side side() const { return m_connection_side; }
+
+ /**
+ * Get the SNI hostname (if sent by the client in the initial handshake)
+ */
+ std::string sni_hostname() const { return m_sni_hostname; }
+
+ /**
+ * Get the SRP identity (if sent by the client in the initial handshake)
+ */
+ std::string srp_identifier() const { return m_srp_identifier; }
+
+ /**
+ * Get the saved master secret
+ */
+ const secure_vector<byte>& master_secret() const
+ { return m_master_secret; }
+
+ /**
+ * Get the session identifier
+ */
+ const std::vector<byte>& session_id() const
+ { return m_identifier; }
+
+ /**
+ * Get the negotiated maximum fragment size (or 0 if default)
+ */
+ size_t fragment_size() const { return m_fragment_size; }
+
+ /**
+ * Is secure renegotiation supported?
+ */
+ bool secure_renegotiation() const
+ { return m_secure_renegotiation_supported; }
+
+ /**
+ * Return the certificate chain of the peer (possibly empty)
+ */
+ std::vector<X509_Certificate> peer_certs() const { return m_peer_certs; }
+
+ /**
+ * Get the wall clock time this session began
+ */
+ std::chrono::system_clock::time_point start_time() const
+ { return m_start_time; }
+
+ /**
+ * Return how long this session has existed (in seconds)
+ */
+ std::chrono::seconds session_age() const;
+
+ /**
+ * Return the session ticket the server gave us
+ */
+ const std::vector<byte>& session_ticket() const { return m_session_ticket; }
+
+ private:
+ enum { TLS_SESSION_PARAM_STRUCT_VERSION = 0x2994e300 };
+
+ std::chrono::system_clock::time_point m_start_time;
+
+ std::vector<byte> m_identifier;
+ std::vector<byte> m_session_ticket; // only used by client side
+ secure_vector<byte> m_master_secret;
+
+ Protocol_Version m_version;
+ u16bit m_ciphersuite;
+ byte m_compression_method;
+ Connection_Side m_connection_side;
+
+ bool m_secure_renegotiation_supported;
+ size_t m_fragment_size;
+
+ std::vector<X509_Certificate> m_peer_certs;
+ std::string m_sni_hostname; // optional
+ std::string m_srp_identifier; // optional
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp
new file mode 100644
index 000000000..0cd74a63a
--- /dev/null
+++ b/src/tls/tls_session_key.cpp
@@ -0,0 +1,89 @@
+/*
+* TLS Session Key
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Session_Keys Constructor
+*/
+Session_Keys::Session_Keys(Handshake_State* state,
+ const secure_vector<byte>& pre_master_secret,
+ bool resuming)
+ {
+ const size_t mac_keylen = output_length_of(state->suite.mac_algo());
+ const size_t cipher_keylen = state->suite.cipher_keylen();
+
+ size_t cipher_ivlen = 0;
+ if(have_block_cipher(state->suite.cipher_algo()))
+ cipher_ivlen = block_size_of(state->suite.cipher_algo());
+
+ const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen);
+
+ const byte MASTER_SECRET_MAGIC[] = {
+ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 };
+
+ const byte KEY_GEN_MAGIC[] = {
+ 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E };
+
+ std::unique_ptr<KDF> prf(state->protocol_specific_prf());
+
+ if(resuming)
+ {
+ master_sec = pre_master_secret;
+ }
+ else
+ {
+ secure_vector<byte> salt;
+
+ if(state->version() != Protocol_Version::SSL_V3)
+ salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC));
+
+ salt += state->client_hello->random();
+ salt += state->server_hello->random();
+
+ master_sec = prf->derive_key(48, pre_master_secret, salt);
+ }
+
+ secure_vector<byte> salt;
+ if(state->version() != Protocol_Version::SSL_V3)
+ salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC));
+ salt += state->server_hello->random();
+ salt += state->client_hello->random();
+
+ SymmetricKey keyblock = prf->derive_key(prf_gen, master_sec, salt);
+
+ const byte* key_data = keyblock.begin();
+
+ c_mac = SymmetricKey(key_data, mac_keylen);
+ key_data += mac_keylen;
+
+ s_mac = SymmetricKey(key_data, mac_keylen);
+ key_data += mac_keylen;
+
+ c_cipher = SymmetricKey(key_data, cipher_keylen);
+ key_data += cipher_keylen;
+
+ s_cipher = SymmetricKey(key_data, cipher_keylen);
+ key_data += cipher_keylen;
+
+ c_iv = InitializationVector(key_data, cipher_ivlen);
+ key_data += cipher_ivlen;
+
+ s_iv = InitializationVector(key_data, cipher_ivlen);
+ }
+
+}
+
+}
diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h
new file mode 100644
index 000000000..0021694e3
--- /dev/null
+++ b/src/tls/tls_session_key.h
@@ -0,0 +1,52 @@
+/*
+* TLS Session Key
+* (C) 2004-2006,2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_SESSION_KEYS_H__
+#define BOTAN_TLS_SESSION_KEYS_H__
+
+#include <botan/tls_ciphersuite.h>
+#include <botan/tls_exceptn.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* TLS Session Keys
+*/
+class Session_Keys
+ {
+ public:
+ SymmetricKey client_cipher_key() const { return c_cipher; }
+ SymmetricKey server_cipher_key() const { return s_cipher; }
+
+ SymmetricKey client_mac_key() const { return c_mac; }
+ SymmetricKey server_mac_key() const { return s_mac; }
+
+ InitializationVector client_iv() const { return c_iv; }
+ InitializationVector server_iv() const { return s_iv; }
+
+ const secure_vector<byte>& master_secret() const { return master_sec; }
+
+ Session_Keys() {}
+
+ Session_Keys(class Handshake_State* state,
+ const secure_vector<byte>& pre_master,
+ bool resuming);
+
+ private:
+ secure_vector<byte> master_sec;
+ SymmetricKey c_cipher, s_cipher, c_mac, s_mac;
+ InitializationVector c_iv, s_iv;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_session_manager.cpp b/src/tls/tls_session_manager.cpp
new file mode 100644
index 000000000..72eb83c21
--- /dev/null
+++ b/src/tls/tls_session_manager.cpp
@@ -0,0 +1,106 @@
+/*
+* TLS Session Management
+* (C) 2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_session_manager.h>
+#include <botan/hex.h>
+#include <chrono>
+
+namespace Botan {
+
+namespace TLS {
+
+bool Session_Manager_In_Memory::load_from_session_str(
+ const std::string& session_str, Session& session)
+ {
+ // assert(lock is held)
+
+ auto i = m_sessions.find(session_str);
+
+ if(i == m_sessions.end())
+ return false;
+
+ // if session has expired, remove it
+ const auto now = std::chrono::system_clock::now();
+
+ if(i->second.start_time() + session_lifetime() < now)
+ {
+ m_sessions.erase(i);
+ return false;
+ }
+
+ session = i->second;
+ return true;
+ }
+
+bool Session_Manager_In_Memory::load_from_session_id(
+ const std::vector<byte>& session_id, Session& session)
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ return load_from_session_str(hex_encode(session_id), session);
+ }
+
+bool Session_Manager_In_Memory::load_from_host_info(
+ const std::string& hostname, u16bit port, Session& session)
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ std::map<std::string, std::string>::iterator i;
+
+ if(port > 0)
+ i = m_host_sessions.find(hostname + ":" + std::to_string(port));
+ else
+ i = m_host_sessions.find(hostname);
+
+ if(i == m_host_sessions.end())
+ return false;
+
+ if(load_from_session_str(i->second, session))
+ return true;
+
+ // was removed from sessions map, remove m_host_sessions entry
+ m_host_sessions.erase(i);
+
+ return false;
+ }
+
+void Session_Manager_In_Memory::remove_entry(
+ const std::vector<byte>& session_id)
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ auto i = m_sessions.find(hex_encode(session_id));
+
+ if(i != m_sessions.end())
+ m_sessions.erase(i);
+ }
+
+void Session_Manager_In_Memory::save(const Session& session)
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ if(m_max_sessions != 0)
+ {
+ /*
+ This removes randomly based on ordering of session ids.
+ Instead, remove oldest first?
+ */
+ while(m_sessions.size() >= m_max_sessions)
+ m_sessions.erase(m_sessions.begin());
+ }
+
+ const std::string session_id_str = hex_encode(session.session_id());
+
+ m_sessions[session_id_str] = session;
+
+ if(session.side() == CLIENT && session.sni_hostname() != "")
+ m_host_sessions[session.sni_hostname()] = session_id_str;
+ }
+
+}
+
+}
diff --git a/src/tls/tls_session_manager.h b/src/tls/tls_session_manager.h
new file mode 100644
index 000000000..fa1ecae39
--- /dev/null
+++ b/src/tls/tls_session_manager.h
@@ -0,0 +1,127 @@
+/*
+* TLS Session Manager
+* (C) 2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_SESSION_MANAGER_H__
+#define BOTAN_TLS_SESSION_MANAGER_H__
+
+#include <botan/tls_session.h>
+#include <mutex>
+#include <chrono>
+#include <map>
+
+namespace Botan {
+
+namespace TLS {
+
+/**
+* Session_Manager is an interface to systems which can save
+* session parameters for supporting session resumption.
+*
+* Saving sessions is done on a best-effort basis; an implementation is
+* allowed to drop sessions due to space constraints.
+*
+* Implementations should strive to be thread safe
+*/
+class BOTAN_DLL Session_Manager
+ {
+ public:
+ /**
+ * Try to load a saved session (server side)
+ * @param session_id the session identifier we are trying to resume
+ * @param session will be set to the saved session data (if found),
+ or not modified if not found
+ * @return true if session was modified
+ */
+ virtual bool load_from_session_id(const std::vector<byte>& session_id,
+ Session& session) = 0;
+
+ /**
+ * Try to load a saved session (client side)
+ * @param hostname of the host we are connecting to
+ * @param port the port number if we know it, or 0 if unknown
+ * @param session will be set to the saved session data (if found),
+ or not modified if not found
+ * @return true if session was modified
+ */
+ virtual bool load_from_host_info(const std::string& hostname, u16bit port,
+ Session& session) = 0;
+
+ /**
+ * Remove this session id from the cache, if it exists
+ */
+ virtual void remove_entry(const std::vector<byte>& session_id) = 0;
+
+ /**
+ * Save a session on a best effort basis; the manager may not in
+ * fact be able to save the session for whatever reason; this is
+ * not an error. Caller cannot assume that calling save followed
+ * immediately by load_from_* will result in a successful lookup.
+ *
+ * @param session to save
+ */
+ virtual void save(const Session& session) = 0;
+
+ /**
+ * Return the allowed lifetime of a session; beyond this time,
+ * sessions are not resumed. Returns 0 if unknown/no explicit
+ * expiration policy.
+ */
+ virtual std::chrono::seconds session_lifetime() const = 0;
+
+ virtual ~Session_Manager() {}
+ };
+
+/**
+* A simple implementation of Session_Manager that just saves
+* values in memory, with no persistance abilities
+*/
+class BOTAN_DLL Session_Manager_In_Memory : public Session_Manager
+ {
+ public:
+ /**
+ * @param max_sessions a hint on the maximum number of sessions
+ * to keep in memory at any one time. (If zero, don't cap)
+ * @param session_lifetime sessions are expired after this many
+ * seconds have elapsed from initial handshake.
+ */
+ Session_Manager_In_Memory(size_t max_sessions = 1000,
+ std::chrono::seconds session_lifetime = std::chrono::seconds(7200)) :
+ m_max_sessions(max_sessions),
+ m_session_lifetime(session_lifetime)
+ {}
+
+ bool load_from_session_id(const std::vector<byte>& session_id,
+ Session& session);
+
+ bool load_from_host_info(const std::string& hostname, u16bit port,
+ Session& session);
+
+ void remove_entry(const std::vector<byte>& session_id);
+
+ void save(const Session& session_data);
+
+ std::chrono::seconds session_lifetime() const { return m_session_lifetime; }
+
+ private:
+ bool load_from_session_str(const std::string& session_str,
+ Session& session);
+
+ std::mutex m_mutex;
+
+ size_t m_max_sessions;
+
+ std::chrono::seconds m_session_lifetime;
+
+ std::map<std::string, Session> m_sessions; // hex(session_id) -> session
+ std::map<std::string, std::string> m_host_sessions;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_suite_info.cpp b/src/tls/tls_suite_info.cpp
new file mode 100644
index 000000000..997bda428
--- /dev/null
+++ b/src/tls/tls_suite_info.cpp
@@ -0,0 +1,317 @@
+/*
+* TLS Cipher Suite
+* (C) 2004-2010,2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_ciphersuite.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Ciphersuite Ciphersuite::by_id(u16bit suite)
+ {
+ // Automatically generated by a Python script from the IANA values
+
+ switch(suite)
+ {
+ case 0x0013: // DHE_DSS_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "3DES", 24);
+
+ case 0x0032: // DHE_DSS_WITH_AES_128_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "AES-128", 16);
+
+ case 0x0040: // DHE_DSS_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("DSA", "DH", "SHA-256", "AES-128", 16);
+
+ case 0x0038: // DHE_DSS_WITH_AES_256_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "AES-256", 32);
+
+ case 0x006A: // DHE_DSS_WITH_AES_256_CBC_SHA256
+ return Ciphersuite("DSA", "DH", "SHA-256", "AES-256", 32);
+
+ case 0x0044: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "Camellia-128", 16);
+
+ case 0x00BD: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("DSA", "DH", "SHA-256", "Camellia-128", 16);
+
+ case 0x0087: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "Camellia-256", 32);
+
+ case 0x00C3: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
+ return Ciphersuite("DSA", "DH", "SHA-256", "Camellia-256", 32);
+
+ case 0x0066: // DHE_DSS_WITH_RC4_128_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "ARC4", 16);
+
+ case 0x0099: // DHE_DSS_WITH_SEED_CBC_SHA
+ return Ciphersuite("DSA", "DH", "SHA-1", "SEED", 16);
+
+ case 0x008F: // DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "DHE_PSK", "SHA-1", "3DES", 24);
+
+ case 0x0090: // DHE_PSK_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "DHE_PSK", "SHA-1", "AES-128", 16);
+
+ case 0x00B2: // DHE_PSK_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("", "DHE_PSK", "SHA-256", "AES-128", 16);
+
+ case 0x0091: // DHE_PSK_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "DHE_PSK", "SHA-1", "AES-256", 32);
+
+ case 0x00B3: // DHE_PSK_WITH_AES_256_CBC_SHA384
+ return Ciphersuite("", "DHE_PSK", "SHA-384", "AES-256", 32);
+
+ case 0xC096: // DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("", "DHE_PSK", "SHA-256", "Camellia-128", 16);
+
+ case 0xC097: // DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ return Ciphersuite("", "DHE_PSK", "SHA-384", "Camellia-256", 32);
+
+ case 0x008E: // DHE_PSK_WITH_RC4_128_SHA
+ return Ciphersuite("", "DHE_PSK", "SHA-1", "ARC4", 16);
+
+ case 0x0016: // DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "3DES", 24);
+
+ case 0x0033: // DHE_RSA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "AES-128", 16);
+
+ case 0x0067: // DHE_RSA_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("RSA", "DH", "SHA-256", "AES-128", 16);
+
+ case 0x0039: // DHE_RSA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "AES-256", 32);
+
+ case 0x006B: // DHE_RSA_WITH_AES_256_CBC_SHA256
+ return Ciphersuite("RSA", "DH", "SHA-256", "AES-256", 32);
+
+ case 0x0045: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "Camellia-128", 16);
+
+ case 0x00BE: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("RSA", "DH", "SHA-256", "Camellia-128", 16);
+
+ case 0x0088: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "Camellia-256", 32);
+
+ case 0x00C4: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ return Ciphersuite("RSA", "DH", "SHA-256", "Camellia-256", 32);
+
+ case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA
+ return Ciphersuite("RSA", "DH", "SHA-1", "SEED", 16);
+
+ case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "3DES", 24);
+
+ case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "AES-128", 16);
+
+ case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("", "DH", "SHA-256", "AES-128", 16);
+
+ case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "AES-256", 32);
+
+ case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256
+ return Ciphersuite("", "DH", "SHA-256", "AES-256", 32);
+
+ case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "Camellia-128", 16);
+
+ case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("", "DH", "SHA-256", "Camellia-128", 16);
+
+ case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "Camellia-256", 32);
+
+ case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256
+ return Ciphersuite("", "DH", "SHA-256", "Camellia-256", 32);
+
+ case 0x0018: // DH_anon_WITH_RC4_128_MD5
+ return Ciphersuite("", "DH", "MD5", "ARC4", 16);
+
+ case 0x009B: // DH_anon_WITH_SEED_CBC_SHA
+ return Ciphersuite("", "DH", "SHA-1", "SEED", 16);
+
+ case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("ECDSA", "ECDH", "SHA-1", "3DES", 24);
+
+ case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("ECDSA", "ECDH", "SHA-1", "AES-128", 16);
+
+ case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("ECDSA", "ECDH", "SHA-256", "AES-128", 16);
+
+ case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("ECDSA", "ECDH", "SHA-1", "AES-256", 32);
+
+ case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ return Ciphersuite("ECDSA", "ECDH", "SHA-384", "AES-256", 32);
+
+ case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("ECDSA", "ECDH", "SHA-256", "Camellia-128", 16);
+
+ case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ return Ciphersuite("ECDSA", "ECDH", "SHA-384", "Camellia-256", 32);
+
+ case 0xC007: // ECDHE_ECDSA_WITH_RC4_128_SHA
+ return Ciphersuite("ECDSA", "ECDH", "SHA-1", "ARC4", 16);
+
+ case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "ECDHE_PSK", "SHA-1", "3DES", 24);
+
+ case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "ECDHE_PSK", "SHA-1", "AES-128", 16);
+
+ case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("", "ECDHE_PSK", "SHA-256", "AES-128", 16);
+
+ case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "ECDHE_PSK", "SHA-1", "AES-256", 32);
+
+ case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ return Ciphersuite("", "ECDHE_PSK", "SHA-384", "AES-256", 32);
+
+ case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("", "ECDHE_PSK", "SHA-256", "Camellia-128", 16);
+
+ case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ return Ciphersuite("", "ECDHE_PSK", "SHA-384", "Camellia-256", 32);
+
+ case 0xC033: // ECDHE_PSK_WITH_RC4_128_SHA
+ return Ciphersuite("", "ECDHE_PSK", "SHA-1", "ARC4", 16);
+
+ case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("RSA", "ECDH", "SHA-1", "3DES", 24);
+
+ case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("RSA", "ECDH", "SHA-1", "AES-128", 16);
+
+ case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("RSA", "ECDH", "SHA-256", "AES-128", 16);
+
+ case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("RSA", "ECDH", "SHA-1", "AES-256", 32);
+
+ case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ return Ciphersuite("RSA", "ECDH", "SHA-384", "AES-256", 32);
+
+ case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("RSA", "ECDH", "SHA-256", "Camellia-128", 16);
+
+ case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ return Ciphersuite("RSA", "ECDH", "SHA-384", "Camellia-256", 32);
+
+ case 0xC011: // ECDHE_RSA_WITH_RC4_128_SHA
+ return Ciphersuite("RSA", "ECDH", "SHA-1", "ARC4", 16);
+
+ case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "ECDH", "SHA-1", "3DES", 24);
+
+ case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "ECDH", "SHA-1", "AES-128", 16);
+
+ case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "ECDH", "SHA-1", "AES-256", 32);
+
+ case 0xC016: // ECDH_anon_WITH_RC4_128_SHA
+ return Ciphersuite("", "ECDH", "SHA-1", "ARC4", 16);
+
+ case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "PSK", "SHA-1", "3DES", 24);
+
+ case 0x008C: // PSK_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "PSK", "SHA-1", "AES-128", 16);
+
+ case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("", "PSK", "SHA-256", "AES-128", 16);
+
+ case 0x008D: // PSK_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "PSK", "SHA-1", "AES-256", 32);
+
+ case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384
+ return Ciphersuite("", "PSK", "SHA-384", "AES-256", 32);
+
+ case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("", "PSK", "SHA-256", "Camellia-128", 16);
+
+ case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384
+ return Ciphersuite("", "PSK", "SHA-384", "Camellia-256", 32);
+
+ case 0x008A: // PSK_WITH_RC4_128_SHA
+ return Ciphersuite("", "PSK", "SHA-1", "ARC4", 16);
+
+ case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "3DES", 24);
+
+ case 0x002F: // RSA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "AES-128", 16);
+
+ case 0x003C: // RSA_WITH_AES_128_CBC_SHA256
+ return Ciphersuite("RSA", "RSA", "SHA-256", "AES-128", 16);
+
+ case 0x0035: // RSA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "AES-256", 32);
+
+ case 0x003D: // RSA_WITH_AES_256_CBC_SHA256
+ return Ciphersuite("RSA", "RSA", "SHA-256", "AES-256", 32);
+
+ case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "Camellia-128", 16);
+
+ case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256
+ return Ciphersuite("RSA", "RSA", "SHA-256", "Camellia-128", 16);
+
+ case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "Camellia-256", 32);
+
+ case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256
+ return Ciphersuite("RSA", "RSA", "SHA-256", "Camellia-256", 32);
+
+ case 0x0004: // RSA_WITH_RC4_128_MD5
+ return Ciphersuite("RSA", "RSA", "MD5", "ARC4", 16);
+
+ case 0x0005: // RSA_WITH_RC4_128_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "ARC4", 16);
+
+ case 0x0096: // RSA_WITH_SEED_CBC_SHA
+ return Ciphersuite("RSA", "RSA", "SHA-1", "SEED", 16);
+
+ case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "3DES", 24);
+
+ case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA
+ return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "AES-128", 16);
+
+ case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA
+ return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "AES-256", 32);
+
+ case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "3DES", 24);
+
+ case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "AES-128", 16);
+
+ case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "AES-256", 32);
+
+ case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA
+ return Ciphersuite("", "SRP_SHA", "SHA-1", "3DES", 24);
+
+ case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA
+ return Ciphersuite("", "SRP_SHA", "SHA-1", "AES-128", 16);
+
+ case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA
+ return Ciphersuite("", "SRP_SHA", "SHA-1", "AES-256", 32);
+ }
+
+ return Ciphersuite(); // some unknown ciphersuite
+ }
+
+}
+
+}
diff --git a/src/tls/tls_version.cpp b/src/tls/tls_version.cpp
new file mode 100644
index 000000000..82dce0be9
--- /dev/null
+++ b/src/tls/tls_version.cpp
@@ -0,0 +1,33 @@
+/*
+* TLS Protocol Version Management
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/tls_version.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace TLS {
+
+std::string Protocol_Version::to_string() const
+ {
+ const byte maj = major_version();
+ const byte min = minor_version();
+
+ // Some very new or very old protocol?
+ if(maj != 3)
+ return "Protocol " + std::to_string(maj) + "." + std::to_string(min);
+
+ if(maj == 3 && min == 0)
+ return "SSL v3";
+
+ // The TLS v1.[0123...] case
+ return "TLS v1." + std::to_string(min-1);
+ }
+
+}
+
+}
diff --git a/src/tls/tls_version.h b/src/tls/tls_version.h
new file mode 100644
index 000000000..aa689b300
--- /dev/null
+++ b/src/tls/tls_version.h
@@ -0,0 +1,87 @@
+/*
+* TLS Protocol Version Management
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_PROTOCOL_VERSION_H__
+#define BOTAN_TLS_PROTOCOL_VERSION_H__
+
+#include <botan/get_byte.h>
+#include <string>
+
+namespace Botan {
+
+namespace TLS {
+
+class BOTAN_DLL Protocol_Version
+ {
+ public:
+ enum Version_Code {
+ SSL_V3 = 0x0300,
+ TLS_V10 = 0x0301,
+ TLS_V11 = 0x0302,
+ TLS_V12 = 0x0303
+ };
+
+ Protocol_Version() : m_version(0) {}
+
+ Protocol_Version(Version_Code named_version) :
+ m_version(static_cast<u16bit>(named_version)) {}
+
+ Protocol_Version(byte major, byte minor) :
+ m_version((static_cast<u16bit>(major) << 8) | minor) {}
+
+ /**
+ * Get the major version of the protocol version
+ */
+ byte major_version() const { return get_byte(0, m_version); }
+
+ /**
+ * Get the minor version of the protocol version
+ */
+ byte minor_version() const { return get_byte(1, m_version); }
+
+ bool operator==(const Protocol_Version& other) const
+ {
+ return (m_version == other.m_version);
+ }
+
+ bool operator!=(const Protocol_Version& other) const
+ {
+ return (m_version != other.m_version);
+ }
+
+ bool operator>=(const Protocol_Version& other) const
+ {
+ return (m_version >= other.m_version);
+ }
+
+ bool operator>(const Protocol_Version& other) const
+ {
+ return (m_version > other.m_version);
+ }
+
+ bool operator<=(const Protocol_Version& other) const
+ {
+ return (m_version <= other.m_version);
+ }
+
+ bool operator<(const Protocol_Version& other) const
+ {
+ return (m_version < other.m_version);
+ }
+
+ std::string to_string() const;
+
+ private:
+ u16bit m_version;
+ };
+
+}
+
+}
+
+#endif
+
diff --git a/src/utils/assert.cpp b/src/utils/assert.cpp
index 29af831d8..3747912d6 100644
--- a/src/utils/assert.cpp
+++ b/src/utils/assert.cpp
@@ -21,7 +21,7 @@ void assertion_failure(const char* expr_str,
format << "Assertion " << expr_str << " failed ";
- if(msg)
+ if(msg && msg[0] != 0)
format << "(" << msg << ") ";
if(func)
diff --git a/src/utils/assert.h b/src/utils/assert.h
index 67ca665e3..d68f683a6 100644
--- a/src/utils/assert.h
+++ b/src/utils/assert.h
@@ -36,6 +36,16 @@ void assertion_failure(const char* expr_str,
__LINE__); \
} while(0)
+#define BOTAN_ASSERT_NONNULL(ptr) \
+ do { \
+ if(static_cast<bool>(ptr) == false) \
+ Botan::assertion_failure(#ptr " is not null", \
+ "", \
+ BOTAN_ASSERT_FUNCTION, \
+ __FILE__, \
+ __LINE__); \
+ } while(0)
+
/*
* Unfortunately getting the function name from the preprocessor
* isn't standard in C++98 (C++0x uses C99's __func__)
diff --git a/src/utils/calendar.cpp b/src/utils/calendar.cpp
new file mode 100644
index 000000000..14f0113f2
--- /dev/null
+++ b/src/utils/calendar.cpp
@@ -0,0 +1,52 @@
+/*
+* Calendar Functions
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/calendar.h>
+#include <botan/exceptn.h>
+#include <ctime>
+
+namespace Botan {
+
+namespace {
+
+std::tm do_gmtime(std::time_t time_val)
+ {
+ std::tm tm;
+
+#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
+ gmtime_s(&tm, &time_val); // Windows
+#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
+ gmtime_r(&time_val, &tm); // Unix/SUSv2
+#else
+ std::tm* tm_p = std::gmtime(&time_val);
+ if (tm_p == 0)
+ throw Encoding_Error("time_t_to_tm could not convert");
+ tm = *tm_p;
+#endif
+
+ return tm;
+ }
+
+}
+
+/*
+* Convert a time_point to a calendar_point
+*/
+calendar_point calendar_value(
+ const std::chrono::system_clock::time_point& time_point)
+ {
+ std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point));
+
+ return calendar_point(tm.tm_year + 1900,
+ tm.tm_mon + 1,
+ tm.tm_mday,
+ tm.tm_hour,
+ tm.tm_min,
+ tm.tm_sec);
+ }
+
+}
diff --git a/src/utils/time.h b/src/utils/calendar.h
index fcc956df2..d617cc9a0 100644
--- a/src/utils/time.h
+++ b/src/utils/calendar.h
@@ -1,14 +1,15 @@
/*
-* Time Functions
+* Calendar Functions
* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_TIME_H__
-#define BOTAN_TIME_H__
+#ifndef BOTAN_CALENDAR_H__
+#define BOTAN_CALENDAR_H__
#include <botan/types.h>
+#include <chrono>
namespace Botan {
@@ -50,21 +51,12 @@ struct BOTAN_DLL calendar_point
year(y), month(mon), day(d), hour(h), minutes(min), seconds(sec) {}
};
-/**
+/*
* @param time_point a time point from the system clock
* @return calendar_point object representing this time point
*/
-BOTAN_DLL calendar_point calendar_value(u64bit time_point);
-
-/**
-* @return seconds resolution timestamp, unknown epoch
-*/
-BOTAN_DLL u64bit system_time();
-
-/**
-* @return nanoseconds resolution timestamp, unknown epoch
-*/
-BOTAN_DLL u64bit get_nanoseconds_clock();
+BOTAN_DLL calendar_point calendar_value(
+ const std::chrono::system_clock::time_point& time_point);
}
diff --git a/src/utils/charset.cpp b/src/utils/charset.cpp
index 8e20e6492..7ee637f80 100644
--- a/src/utils/charset.cpp
+++ b/src/utils/charset.cpp
@@ -119,7 +119,7 @@ std::string transcode(const std::string& str,
return ucs2_to_latin1(str);
throw Invalid_Argument("Unknown transcoding operation from " +
- to_string(from) + " to " + to_string(to));
+ std::to_string(from) + " to " + std::to_string(to));
}
/*
diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h
index ad85ac4fe..cdc6417ec 100644
--- a/src/utils/cpuid.h
+++ b/src/utils/cpuid.h
@@ -103,7 +103,7 @@ class BOTAN_DLL CPUID
CPUID_MOVBE_BIT = 54,
CPUID_AESNI_BIT = 57,
CPUID_AVX_BIT = 60,
- CPUID_RDRAND_BIT = 61
+ CPUID_RDRAND_BIT = 62
};
static bool x86_processor_flags_has(u64bit bit)
diff --git a/src/utils/datastor/datastor.cpp b/src/utils/datastor/datastor.cpp
index 49e7b2dda..d65b3f1ac 100644
--- a/src/utils/datastor/datastor.cpp
+++ b/src/utils/datastor/datastor.cpp
@@ -14,16 +14,6 @@
namespace Botan {
/*
-* Default Matcher transform operation (identity)
-*/
-std::pair<std::string, std::string>
-Data_Store::Matcher::transform(const std::string& key,
- const std::string& value) const
- {
- return std::make_pair(key, value);
- }
-
-/*
* Data_Store Equality Comparison
*/
bool Data_Store::operator==(const Data_Store& other) const
@@ -42,26 +32,14 @@ bool Data_Store::has_value(const std::string& key) const
/*
* Search based on an arbitrary predicate
*/
-std::multimap<std::string, std::string>
-Data_Store::search_with(const Matcher& matcher) const
+std::multimap<std::string, std::string> Data_Store::search_for(
+ std::function<bool (std::string, std::string)> predicate) const
{
std::multimap<std::string, std::string> out;
- std::multimap<std::string, std::string>::const_iterator i =
- contents.begin();
-
- while(i != contents.end())
- {
- if(matcher(i->first, i->second))
- {
- std::pair<std::string, std::string> p(
- matcher.transform(i->first, i->second));
-
- multimap_insert(out, p.first, p.second);
- }
-
- ++i;
- }
+ for(auto i = contents.begin(); i != contents.end(); ++i)
+ if(predicate(i->first, i->second))
+ out.insert(std::make_pair(i->first, i->second));
return out;
}
@@ -71,12 +49,9 @@ Data_Store::search_with(const Matcher& matcher) const
*/
std::vector<std::string> Data_Store::get(const std::string& looking_for) const
{
- typedef std::multimap<std::string, std::string>::const_iterator iter;
-
- std::pair<iter, iter> range = contents.equal_range(looking_for);
-
std::vector<std::string> out;
- for(iter i = range.first; i != range.second; ++i)
+ auto range = contents.equal_range(looking_for);
+ for(auto i = range.first; i != range.second; ++i)
out.push_back(i->second);
return out;
}
@@ -97,21 +72,21 @@ std::string Data_Store::get1(const std::string& key) const
}
/*
-* Get a single MemoryVector atom
+* Get a single std::vector atom
*/
-MemoryVector<byte>
+std::vector<byte>
Data_Store::get1_memvec(const std::string& key) const
{
std::vector<std::string> vals = get(key);
if(vals.empty())
- return MemoryVector<byte>();
+ return std::vector<byte>();
if(vals.size() > 1)
throw Invalid_State("Data_Store::get1_memvec: Multiple values for " +
key);
- return hex_decode(vals[0]);
+ return unlock(hex_decode(vals[0]));
}
/*
@@ -144,13 +119,18 @@ void Data_Store::add(const std::string& key, const std::string& val)
*/
void Data_Store::add(const std::string& key, u32bit val)
{
- add(key, to_string(val));
+ add(key, std::to_string(val));
}
/*
* Insert a single key and value
*/
-void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val)
+void Data_Store::add(const std::string& key, const secure_vector<byte>& val)
+ {
+ add(key, hex_encode(&val[0], val.size()));
+ }
+
+void Data_Store::add(const std::string& key, const std::vector<byte>& val)
{
add(key, hex_encode(&val[0], val.size()));
}
diff --git a/src/utils/datastor/datastor.h b/src/utils/datastor/datastor.h
index 8d41b07a8..b471f85e1 100644
--- a/src/utils/datastor/datastor.h
+++ b/src/utils/datastor/datastor.h
@@ -9,6 +9,7 @@
#define BOTAN_DATA_STORE_H__
#include <botan/secmem.h>
+#include <functional>
#include <utility>
#include <string>
#include <vector>
@@ -25,28 +26,16 @@ class BOTAN_DLL Data_Store
/**
* A search function
*/
- class BOTAN_DLL Matcher
- {
- public:
- virtual bool operator()(const std::string&,
- const std::string&) const = 0;
-
- virtual std::pair<std::string, std::string>
- transform(const std::string&, const std::string&) const;
-
- virtual ~Matcher() {}
- };
-
bool operator==(const Data_Store&) const;
- std::multimap<std::string, std::string>
- search_with(const Matcher&) const;
+ std::multimap<std::string, std::string> search_for(
+ std::function<bool (std::string, std::string)> predicate) const;
std::vector<std::string> get(const std::string&) const;
std::string get1(const std::string&) const;
- MemoryVector<byte> get1_memvec(const std::string&) const;
+ std::vector<byte> get1_memvec(const std::string&) const;
u32bit get1_u32bit(const std::string&, u32bit = 0) const;
bool has_value(const std::string&) const;
@@ -54,7 +43,8 @@ class BOTAN_DLL Data_Store
void add(const std::multimap<std::string, std::string>&);
void add(const std::string&, const std::string&);
void add(const std::string&, u32bit);
- void add(const std::string&, const MemoryRegion<byte>&);
+ void add(const std::string&, const secure_vector<byte>&);
+ void add(const std::string&, const std::vector<byte>&);
private:
std::multimap<std::string, std::string> contents;
};
diff --git a/src/utils/dyn_load/dyn_load.cpp b/src/utils/dyn_load/dyn_load.cpp
index 06b8c5df3..51afb1afe 100644
--- a/src/utils/dyn_load/dyn_load.cpp
+++ b/src/utils/dyn_load/dyn_load.cpp
@@ -30,7 +30,7 @@ void raise_runtime_loader_exception(const std::string& lib_name,
Dynamically_Loaded_Library::Dynamically_Loaded_Library(
const std::string& library) :
- lib_name(library), lib(0)
+ lib_name(library), lib(nullptr)
{
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
lib = ::dlopen(lib_name.c_str(), RTLD_LAZY);
@@ -60,7 +60,7 @@ Dynamically_Loaded_Library::~Dynamically_Loaded_Library()
void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol)
{
- void* addr = 0;
+ void* addr = nullptr;
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
addr = ::dlsym(lib, symbol.c_str());
diff --git a/src/utils/dyn_load/dyn_load.h b/src/utils/dyn_load/dyn_load.h
index b37a52e84..4d5cfb296 100644
--- a/src/utils/dyn_load/dyn_load.h
+++ b/src/utils/dyn_load/dyn_load.h
@@ -59,6 +59,9 @@ class Dynamically_Loaded_Library
}
private:
+ Dynamically_Loaded_Library(const Dynamically_Loaded_Library&);
+ Dynamically_Loaded_Library& operator=(const Dynamically_Loaded_Library&);
+
std::string lib_name;
void* lib;
};
diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h
index 3797a5478..02fb16a66 100644
--- a/src/utils/exceptn.h
+++ b/src/utils/exceptn.h
@@ -56,7 +56,7 @@ struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
{
Invalid_Key_Length(const std::string& name, size_t length) :
Invalid_Argument(name + " cannot accept a key of length " +
- to_string(length))
+ std::to_string(length))
{}
};
@@ -78,7 +78,7 @@ struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
{
Invalid_IV_Length(const std::string& mode, size_t bad_len) :
- Invalid_Argument("IV length " + to_string(bad_len) +
+ Invalid_Argument("IV length " + std::to_string(bad_len) +
" is invalid for " + mode)
{}
};
diff --git a/src/utils/info.txt b/src/utils/info.txt
index fcf16bd5a..a1079d47b 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -4,19 +4,16 @@ load_on always
<source>
assert.cpp
+calendar.cpp
charset.cpp
cpuid.cpp
-mlock.cpp
parsing.cpp
-time.cpp
-ui.cpp
version.cpp
</source>
<header:internal>
assert.h
bit_ops.h
-mlock.h
prefetch.h
rounding.h
stl_util.h
@@ -25,6 +22,7 @@ xor_buf.h
<header:public>
bswap.h
+calendar.h
charset.h
cpuid.h
exceptn.h
@@ -32,9 +30,7 @@ loadstor.h
mem_ops.h
parsing.h
rotate.h
-time.h
types.h
-ui.h
version.h
get_byte.h
</header:public>
diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp
deleted file mode 100644
index 800425665..000000000
--- a/src/utils/mlock.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-* Memory Locking Functions
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mlock.h>
-
-#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- #include <sys/types.h>
- #include <sys/mman.h>
-#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
- #include <windows.h>
-#endif
-
-namespace Botan {
-
-bool has_mlock()
- {
- byte buf[4096];
- if(!lock_mem(&buf, sizeof(buf)))
- return false;
- unlock_mem(&buf, sizeof(buf));
- return true;
- }
-
-/*
-* Lock an area of memory into RAM
-*/
-bool lock_mem(void* ptr, size_t bytes)
- {
-#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- return (::mlock(static_cast<char*>(ptr), bytes) == 0);
-#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
- return (::VirtualLock(ptr, bytes) != 0);
-#else
- return false;
-#endif
- }
-
-/*
-* Unlock a previously locked region of memory
-*/
-void unlock_mem(void* ptr, size_t bytes)
- {
-#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- ::munlock(static_cast<char*>(ptr), bytes);
-#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
- ::VirtualUnlock(ptr, bytes);
-#endif
- }
-
-}
diff --git a/src/utils/mlock.h b/src/utils/mlock.h
deleted file mode 100644
index 88788472d..000000000
--- a/src/utils/mlock.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* Memory Locking Functions
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_MLOCK_H__
-#define BOTAN_MLOCK_H__
-
-#include <botan/types.h>
-
-namespace Botan {
-
-/**
-* Check if we can at least potentially lock memory
-*/
-bool has_mlock();
-
-/**
-* Lock memory into RAM if possible
-* @param addr the start of the memory block
-* @param length the length of the memory block in bytes
-* @returns true if successful, false otherwise
-*/
-bool lock_mem(void* addr, size_t length);
-
-/**
-* Unlock memory locked with lock_mem()
-* @param addr the start of the memory block
-* @param length the length of the memory block in bytes
-*/
-void unlock_mem(void* addr, size_t length);
-
-}
-
-#endif
diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp
index 9ec00040c..c3d7f00f7 100644
--- a/src/utils/parsing.cpp
+++ b/src/utils/parsing.cpp
@@ -13,53 +13,6 @@
namespace Botan {
/*
-* Convert a string into an integer
-*/
-u32bit to_u32bit(const std::string& number)
- {
- u32bit n = 0;
-
- for(std::string::const_iterator i = number.begin(); i != number.end(); ++i)
- {
- const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10;
-
- if(*i == ' ')
- continue;
-
- byte digit = Charset::char2digit(*i);
-
- if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5))
- throw Decoding_Error("to_u32bit: Integer overflow");
- n *= 10;
- n += digit;
- }
- return n;
- }
-
-/*
-* Convert an integer into a string
-*/
-std::string to_string(u64bit n, size_t min_len)
- {
- std::string lenstr;
- if(n)
- {
- while(n > 0)
- {
- lenstr = Charset::digit2char(n % 10) + lenstr;
- n /= 10;
- }
- }
- else
- lenstr = "0";
-
- while(lenstr.size() < min_len)
- lenstr = "0" + lenstr;
-
- return lenstr;
- }
-
-/*
* Convert a string into a time duration
*/
u32bit timespec_to_u32bit(const std::string& timespec)
@@ -106,7 +59,7 @@ std::vector<std::string> parse_algorithm_name(const std::string& namex)
elems.push_back(name.substr(0, name.find('(')));
name = name.substr(name.find('('));
- for(std::string::const_iterator i = name.begin(); i != name.end(); ++i)
+ for(auto i = name.begin(); i != name.end(); ++i)
{
char c = *i;
@@ -155,7 +108,7 @@ std::vector<std::string> split_on(const std::string& str, char delim)
if(str == "") return elems;
std::string substr;
- for(std::string::const_iterator i = str.begin(); i != str.end(); ++i)
+ for(auto i = str.begin(); i != str.end(); ++i)
{
if(*i == delim)
{
@@ -175,6 +128,23 @@ std::vector<std::string> split_on(const std::string& str, char delim)
}
/*
+* Join a string
+*/
+std::string string_join(const std::vector<std::string>& strs, char delim)
+ {
+ std::string out = "";
+
+ for(size_t i = 0; i != strs.size(); ++i)
+ {
+ if(i != 0)
+ out += delim;
+ out += strs[i];
+ }
+
+ return out;
+ }
+
+/*
* Parse an ASN.1 OID string
*/
std::vector<u32bit> parse_asn1_oid(const std::string& oid)
@@ -182,7 +152,7 @@ std::vector<u32bit> parse_asn1_oid(const std::string& oid)
std::string substring;
std::vector<u32bit> oid_elems;
- for(std::string::const_iterator i = oid.begin(); i != oid.end(); ++i)
+ for(auto i = oid.begin(); i != oid.end(); ++i)
{
char c = *i;
@@ -212,8 +182,8 @@ std::vector<u32bit> parse_asn1_oid(const std::string& oid)
*/
bool x500_name_cmp(const std::string& name1, const std::string& name2)
{
- std::string::const_iterator p1 = name1.begin();
- std::string::const_iterator p2 = name2.begin();
+ auto p1 = name1.begin();
+ auto p2 = name2.begin();
while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
@@ -258,9 +228,9 @@ u32bit string_to_ipv4(const std::string& str)
u32bit ip = 0;
- for(size_t i = 0; i != parts.size(); ++i)
+ for(auto part = parts.begin(); part != parts.end(); ++part)
{
- u32bit octet = to_u32bit(parts[i]);
+ u32bit octet = to_u32bit(*part);
if(octet > 255)
throw Decoding_Error("Invalid IP string " + str);
@@ -282,10 +252,23 @@ std::string ipv4_to_string(u32bit ip)
{
if(i)
str += ".";
- str += to_string(get_byte(i, ip));
+ str += std::to_string(get_byte(i, ip));
}
return str;
}
+std::string replace_char(const std::string& str,
+ char from_char,
+ char to_char)
+ {
+ std::string out = str;
+
+ for(size_t i = 0; i != out.size(); ++i)
+ if(out[i] == from_char)
+ out[i] = to_char;
+
+ return out;
+ }
+
}
diff --git a/src/utils/parsing.h b/src/utils/parsing.h
index 12370bf2b..12a31a7dd 100644
--- a/src/utils/parsing.h
+++ b/src/utils/parsing.h
@@ -32,6 +32,25 @@ BOTAN_DLL std::vector<std::string> split_on(
const std::string& str, char delim);
/**
+* Replace a character in a string
+* @param str the input string
+* @param from_char the character to replace
+* @return to_char the character to replace it with
+*/
+BOTAN_DLL std::string replace_char(const std::string& str,
+ char from_char,
+ char to_char);
+
+/**
+* Join a string
+* @param strs strings to join
+* @param delim the delimitor
+* @return string joined by delim
+*/
+BOTAN_DLL std::string string_join(const std::vector<std::string>& strs,
+ char delim);
+
+/**
* Parse an ASN.1 OID
* @param oid the OID in string form
* @return OID components
@@ -48,19 +67,12 @@ BOTAN_DLL bool x500_name_cmp(const std::string& name1,
const std::string& name2);
/**
-* Convert a number to a string
-* @param n the integer to convert to a string
-* @param min_len the min length of the output string
-* @return n convert to a string
-*/
-BOTAN_DLL std::string to_string(u64bit n, size_t min_len = 0);
-
-/**
* Convert a string to a number
* @param str the string to convert
* @return number value of the string
*/
-BOTAN_DLL u32bit to_u32bit(const std::string& str);
+inline u32bit to_u32bit(const std::string& str)
+ { return std::stoul(str); }
/**
* Convert a time specification to a number
diff --git a/src/utils/rounding.h b/src/utils/rounding.h
index c77ab9b52..4ddd7a432 100644
--- a/src/utils/rounding.h
+++ b/src/utils/rounding.h
@@ -21,6 +21,9 @@ namespace Botan {
template<typename T>
inline T round_up(T n, T align_to)
{
+ if(align_to == 0)
+ return n;
+
if(n % align_to || n == 0)
n += align_to - (n % align_to);
return n;
@@ -35,9 +38,24 @@ inline T round_up(T n, T align_to)
template<typename T>
inline T round_down(T n, T align_to)
{
+ if(align_to == 0)
+ return n;
+
return (n - (n % align_to));
}
+/**
+* Clamp
+*/
+inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound)
+ {
+ if(n < lower_bound)
+ return lower_bound;
+ if(n > upper_bound)
+ return upper_bound;
+ return n;
+ }
+
}
#endif
diff --git a/src/utils/stl_util.h b/src/utils/stl_util.h
index 0e0617d5b..1a62e8fe7 100644
--- a/src/utils/stl_util.h
+++ b/src/utils/stl_util.h
@@ -8,31 +8,12 @@
#ifndef BOTAN_STL_UTIL_H__
#define BOTAN_STL_UTIL_H__
+#include <vector>
#include <map>
namespace Botan {
-/**
-* Copy-on-Predicate Algorithm
-* @param current the first iterator value
-* @param end the final iterator value
-* @param dest an output iterator
-* @param copy_p the predicate
-*/
-template<typename InputIterator, typename OutputIterator, typename Predicate>
-OutputIterator copy_if(InputIterator current, InputIterator end,
- OutputIterator dest, Predicate copy_p)
- {
- while(current != end)
- {
- if(copy_p(*current))
- *dest++ = *current;
- ++current;
- }
- return dest;
- }
-
-/**
+/*
* Searching through a std::map
* @param mapping the map to search
* @param key is what to look for
@@ -44,32 +25,23 @@ inline V search_map(const std::map<K, V>& mapping,
const K& key,
const V& null_result = V())
{
- typename std::map<K, V>::const_iterator i = mapping.find(key);
+ auto i = mapping.find(key);
if(i == mapping.end())
return null_result;
return i->second;
}
-/**
-* Function adaptor for delete operation
-*/
-template<class T>
-class del_fun : public std::unary_function<T, void>
- {
- public:
- void operator()(T* ptr) { delete ptr; }
- };
-
-/**
-* Delete the second half of a pair of objects
-*/
-template<typename Pair>
-void delete2nd(Pair& pair)
+template<typename K, typename V, typename R>
+inline R search_map(const std::map<K, V>& mapping, const K& key,
+ const R& null_result, const R& found_result)
{
- delete pair.second;
+ auto i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return found_result;
}
-/**
+/*
* Insert a key/value pair into a multimap
*/
template<typename K, typename V>
@@ -84,6 +56,19 @@ void multimap_insert(std::multimap<K, V>& multimap,
#endif
}
+/**
+* Existence check for values
+*/
+template<typename T>
+bool value_exists(const std::vector<T>& vec,
+ const T& val)
+ {
+ for(size_t i = 0; i != vec.size(); ++i)
+ if(vec[i] == val)
+ return true;
+ return false;
+ }
+
}
#endif
diff --git a/src/utils/time.cpp b/src/utils/time.cpp
deleted file mode 100644
index 65e808c04..000000000
--- a/src/utils/time.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-* Time Functions
-* (C) 1999-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/time.h>
-#include <botan/exceptn.h>
-#include <ctime>
-
-#if defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
- #include <windows.h>
-#endif
-
-#if defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
- #include <sys/time.h>
-#endif
-
-#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
-
- #ifndef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 199309
- #endif
-
- #include <time.h>
-
- #ifndef CLOCK_REALTIME
- #define CLOCK_REALTIME 0
- #endif
-
-#endif
-
-namespace Botan {
-
-namespace {
-
-/*
-* Combine a two time values into a single one
-*/
-u64bit combine_timers(u32bit seconds, u32bit parts, u32bit parts_hz)
- {
- static const u64bit NANOSECONDS_UNITS = 1000000000;
-
- u64bit res = seconds * NANOSECONDS_UNITS;
- res += parts * (NANOSECONDS_UNITS / parts_hz);
- return res;
- }
-
-std::tm do_gmtime(time_t time_val)
- {
- std::tm tm;
-
-#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
- gmtime_s(&tm, &time_val); // Windows
-#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
- gmtime_r(&time_val, &tm); // Unix/SUSv2
-#else
- std::tm* tm_p = std::gmtime(&time_val);
- if (tm_p == 0)
- throw Encoding_Error("time_t_to_tm could not convert");
- tm = *tm_p;
-#endif
-
- return tm;
- }
-
-}
-
-/*
-* Get the system clock
-*/
-u64bit system_time()
- {
- return static_cast<u64bit>(std::time(0));
- }
-
-/*
-* Convert a time_point to a calendar_point
-*/
-calendar_point calendar_value(u64bit a_time_t)
- {
- std::tm tm = do_gmtime(static_cast<std::time_t>(a_time_t));
-
- return calendar_point(tm.tm_year + 1900,
- tm.tm_mon + 1,
- tm.tm_mday,
- tm.tm_hour,
- tm.tm_min,
- tm.tm_sec);
- }
-
-u64bit get_nanoseconds_clock()
- {
-#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
-
- struct ::timespec tv;
- ::clock_gettime(CLOCK_REALTIME, &tv);
- return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000);
-
-#elif defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
-
- struct ::timeval tv;
- ::gettimeofday(&tv, 0);
- return combine_timers(tv.tv_sec, tv.tv_usec, 1000000);
-
-#elif defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
-
- // Returns time since January 1, 1601 in 100-ns increments
- ::FILETIME tv;
- ::GetSystemTimeAsFileTime(&tv);
- u64bit tstamp = (static_cast<u64bit>(tv.dwHighDateTime) << 32) |
- tv.dwLowDateTime;
-
- return (tstamp * 100); // Scale to 1 nanosecond units
-
-#else
-
- return combine_timers(static_cast<u32bit>(std::time(0)),
- std::clock(), CLOCKS_PER_SEC);
-
-#endif
- }
-
-}
diff --git a/src/utils/types.h b/src/utils/types.h
index 61a55368c..255311580 100644
--- a/src/utils/types.h
+++ b/src/utils/types.h
@@ -39,15 +39,7 @@ typedef signed int s32bit;
/**
* Typedef representing an unsigned 64-bit quantity
*/
-#if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef unsigned __int64 u64bit;
-#elif defined(__KCC)
- typedef unsigned __long_long u64bit;
-#elif defined(__GNUG__)
- __extension__ typedef unsigned long long u64bit;
-#else
- typedef unsigned long long u64bit;
-#endif
+typedef unsigned long long u64bit;
/**
* A default buffer size; typically a memory page
diff --git a/src/utils/ui.cpp b/src/utils/ui.cpp
deleted file mode 100644
index e6c3430ff..000000000
--- a/src/utils/ui.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-* User Interface
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/ui.h>
-
-namespace Botan {
-
-/*
-* Get a passphrase from the user
-*/
-std::string User_Interface::get_passphrase(const std::string&,
- const std::string&,
- UI_Result& action) const
- {
- action = OK;
-
- if(!first_try)
- action = CANCEL_ACTION;
-
- return preset_passphrase;
- }
-
-/*
-* User_Interface Constructor
-*/
-User_Interface::User_Interface(const std::string& preset) :
- preset_passphrase(preset)
- {
- first_try = true;
- }
-
-}
diff --git a/src/utils/ui.h b/src/utils/ui.h
deleted file mode 100644
index f69bb2c6d..000000000
--- a/src/utils/ui.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* User Interface
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_UI_H__
-#define BOTAN_UI_H__
-
-#include <botan/build.h>
-#include <string>
-
-namespace Botan {
-
-/**
-* User Interface
-* Only really used for callbacks for PKCS #8 decryption
-*/
-class BOTAN_DLL User_Interface
- {
- public:
- enum UI_Result { OK, CANCEL_ACTION };
-
- virtual std::string get_passphrase(const std::string&,
- const std::string&,
- UI_Result&) const;
- User_Interface(const std::string& = "");
- virtual ~User_Interface() {}
- protected:
- std::string preset_passphrase;
- mutable bool first_try;
- };
-
-}
-
-#endif
diff --git a/src/utils/xor_buf.h b/src/utils/xor_buf.h
index 3c96dea70..b67d84c50 100644
--- a/src/utils/xor_buf.h
+++ b/src/utils/xor_buf.h
@@ -9,6 +9,7 @@
#define BOTAN_XOR_BUF_H__
#include <botan/types.h>
+#include <vector>
namespace Botan {
@@ -70,6 +71,31 @@ inline void xor_buf(byte out[],
out[i] = in[i] ^ in2[i];
}
+template<typename Alloc, typename Alloc2>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const std::vector<byte, Alloc2>& in,
+ size_t n)
+ {
+ xor_buf(&out[0], &in[0], n);
+ }
+
+template<typename Alloc>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const byte* in,
+ size_t n)
+ {
+ xor_buf(&out[0], in, n);
+ }
+
+template<typename Alloc, typename Alloc2>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const byte* in,
+ const std::vector<byte, Alloc2>& in2,
+ size_t n)
+ {
+ xor_buf(&out[0], &in[0], &in2[0], n);
+ }
+
}
#endif
diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp
index 7dac7be7f..6dcceee74 100644
--- a/src/wrap/python/core.cpp
+++ b/src/wrap/python/core.cpp
@@ -178,7 +178,7 @@ std::string python_kdf2(const std::string& param,
const std::string& masterkey,
u32bit outputlength)
{
- std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
+ std::unique_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
return make_string(
kdf->derive_key(outputlength,
diff --git a/src/wrap/python/filter.cpp b/src/wrap/python/filter.cpp
index e329ed708..eef8b202c 100644
--- a/src/wrap/python/filter.cpp
+++ b/src/wrap/python/filter.cpp
@@ -107,19 +107,19 @@ Filter* make_filter4(const std::string& name,
name);
}
-void append_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+void append_filter(Pipe& pipe, std::unique_ptr<Filter> filter)
{
pipe.append(filter.get());
filter.release();
}
-void prepend_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+void prepend_filter(Pipe& pipe, std::unique_ptr<Filter> filter)
{
pipe.prepend(filter.get());
filter.release();
}
-void do_send(std::auto_ptr<FilterWrapper> filter, const std::string& data)
+void do_send(std::unique_ptr<FilterWrapper> filter, const std::string& data)
{
filter->send_str(data);
}
@@ -128,7 +128,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(rallas_ovls, read_all_as_string, 0, 1)
void export_filters()
{
- class_<Filter, std::auto_ptr<Filter>, boost::noncopyable>
+ class_<Filter, std::unique_ptr<Filter>, boost::noncopyable>
("__Internal_FilterObj", no_init);
def("make_filter", make_filter1,
@@ -142,7 +142,7 @@ void export_filters()
// This might not work - Pipe will delete the filter, but Python
// might have allocated the space with malloc() or who-knows-what -> bad
- class_<FilterWrapper, std::auto_ptr<FilterWrapper>,
+ class_<FilterWrapper, std::unique_ptr<FilterWrapper>,
bases<Filter>, boost::noncopyable>
("FilterObj")
.def("write", pure_virtual(&Py_Filter::write_str))
@@ -150,8 +150,8 @@ void export_filters()
.def("start_msg", &Filter::start_msg, &FilterWrapper::default_start_msg)
.def("end_msg", &Filter::end_msg, &FilterWrapper::default_end_msg);
- implicitly_convertible<std::auto_ptr<FilterWrapper>,
- std::auto_ptr<Filter> >();
+ implicitly_convertible<std::unique_ptr<FilterWrapper>,
+ std::unique_ptr<Filter> >();
void (Pipe::*pipe_write_str)(const std::string&) = &Pipe::write;
void (Pipe::*pipe_process_str)(const std::string&) = &Pipe::process_msg;
diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h
index a7a2e505e..03bdd9156 100644
--- a/src/wrap/python/python_botan.h
+++ b/src/wrap/python/python_botan.h
@@ -24,7 +24,8 @@ class Bad_Size : public Exception
public:
Bad_Size(u32bit got, u32bit expected) :
Exception("Bad size detected in Python/C++ conversion layer: got " +
- to_string(got) + " bytes, expected " + to_string(expected))
+ std::to_string(got) + " bytes, expected " +
+ std::to_string(expected))
{}
};
@@ -33,7 +34,7 @@ inline std::string make_string(const byte input[], u32bit length)
return std::string((const char*)input, length);
}
-inline std::string make_string(const MemoryRegion<byte>& in)
+inline std::string make_string(const secure_vector<byte>& in)
{
return make_string(in.begin(), in.size());
}
diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp
index dc6053503..3ff1edb07 100644
--- a/src/wrap/python/rsa.cpp
+++ b/src/wrap/python/rsa.cpp
@@ -40,7 +40,7 @@ class Py_RSA_PrivateKey
std::string to_ber() const
{
- SecureVector<byte> bits = PKCS8::BER_encode(*rsa_key);
+ secure_vector<byte> bits = PKCS8::BER_encode(*rsa_key);
return std::string(reinterpret_cast<const char*>(&bits[0]),
bits.size());
@@ -140,7 +140,7 @@ class Py_RSA_PublicKey
std::string to_ber() const
{
- SecureVector<byte> bits = X509::BER_encode(*rsa_key);
+ secure_vector<byte> bits = X509::BER_encode(*rsa_key);
return std::string(reinterpret_cast<const char*>(&bits[0]),
bits.size());
diff --git a/src/wrap/python/x509.cpp b/src/wrap/python/x509.cpp
index 4c248890d..0a29ad83a 100644
--- a/src/wrap/python/x509.cpp
+++ b/src/wrap/python/x509.cpp
@@ -63,7 +63,7 @@ void export_x509()
{
vector_to_list<std::string>();
vector_to_list<X509_Certificate>();
- memvec_to_hexstr<MemoryVector<byte> >();
+ memvec_to_hexstr<std::vector<byte> >();
python::class_<X509_Certificate>
("X509_Certificate", python::init<std::string>())