aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/algo_factory/algo_factory.cpp3
-rw-r--r--src/asn1/ber_dec.cpp2
-rw-r--r--src/asn1/der_enc.cpp4
-rw-r--r--src/block/idea_sse2/idea_sse2.cpp1
-rw-r--r--src/block/noekeon/noekeon.h2
-rw-r--r--src/block/noekeon_simd/info.txt7
-rw-r--r--src/block/noekeon_simd/noekeon_simd.cpp161
-rw-r--r--src/block/noekeon_simd/noekeon_simd.h29
-rw-r--r--src/build-data/makefile/nmake.in2
-rw-r--r--src/build-data/makefile/unix.in2
-rw-r--r--src/build-data/makefile/unix_shr.in2
-rw-r--r--src/cert/cvc/cvc_self.cpp4
-rw-r--r--src/cert/cvc/eac_obj.h2
-rw-r--r--src/checksum/crc24/crc24.cpp2
-rw-r--r--src/constructs/aont/package.cpp2
-rw-r--r--src/constructs/cryptobox/cryptobox.cpp14
-rw-r--r--src/constructs/fpe/fpe.cpp2
-rw-r--r--src/constructs/passhash/info.txt9
-rw-r--r--src/constructs/passhash/passhash9.cpp127
-rw-r--r--src/constructs/passhash/passhash9.h35
-rw-r--r--src/engine/gnump/gmp_mem.cpp22
-rw-r--r--src/engine/gnump/gnump_engine.h7
-rw-r--r--src/engine/simd_engine/simd_engine.cpp9
-rw-r--r--src/filters/buf_filt.cpp29
-rw-r--r--src/filters/modes/cbc/cbc.h4
-rw-r--r--src/filters/modes/cfb/cfb.h4
-rw-r--r--src/filters/modes/cts/cts.h4
-rw-r--r--src/filters/modes/xts/xts.cpp47
-rw-r--r--src/filters/modes/xts/xts.h2
-rw-r--r--src/hash/md4/md4.h2
-rw-r--r--src/hash/md4_ia32/md4_ia32.cpp1
-rw-r--r--src/hash/md5_ia32/md5_ia32.cpp1
-rw-r--r--src/hash/sha1/sha160.cpp4
-rw-r--r--src/hash/sha1_ia32/sha1_ia32.cpp1
-rw-r--r--src/kdf/kdf2/kdf2.cpp2
-rw-r--r--src/kdf/mgf1/mgf1.cpp2
-rw-r--r--src/libstate/policy.cpp1
-rw-r--r--src/libstate/scan_name.cpp4
-rw-r--r--src/libstate/scan_name.h4
-rw-r--r--src/math/bigint/bigint.cpp2
-rw-r--r--src/pbe/pbes1/pbes1.cpp6
-rw-r--r--src/pbe/pbes2/pbes2.cpp6
-rw-r--r--src/rng/hmac_rng/hmac_rng.cpp2
-rw-r--r--src/rng/randpool/randpool.cpp2
-rw-r--r--src/s2k/info.txt1
-rw-r--r--src/s2k/pbkdf1/pbkdf1.cpp9
-rw-r--r--src/s2k/pbkdf1/pbkdf1.h8
-rw-r--r--src/s2k/pbkdf2/pbkdf2.cpp10
-rw-r--r--src/s2k/pbkdf2/pbkdf2.h8
-rw-r--r--src/s2k/pgps2k/pgp_s2k.cpp7
-rw-r--r--src/s2k/pgps2k/pgp_s2k.h8
-rw-r--r--src/s2k/s2k.cpp55
-rw-r--r--src/s2k/s2k.h59
-rw-r--r--src/utils/cpuid.cpp2
-rw-r--r--src/utils/debug.cpp33
-rw-r--r--src/utils/debug.h19
-rw-r--r--src/utils/get_byte.h27
-rw-r--r--src/utils/info.txt2
-rw-r--r--src/utils/loadstor.h11
-rw-r--r--src/utils/parsing.cpp2
-rw-r--r--src/utils/simd_32/simd_32.h16
-rw-r--r--src/utils/simd_32/simd_altivec.h5
-rw-r--r--src/utils/simd_32/simd_scalar.h8
-rw-r--r--src/utils/simd_32/simd_sse.h5
-rw-r--r--src/wrap/sqlite/codec.cpp123
-rw-r--r--src/wrap/sqlite/codec.h127
-rw-r--r--src/wrap/sqlite/codecext.cpp261
-rw-r--r--src/wrap/sqlite/readme.txt36
-rw-r--r--src/wrap/sqlite/sqlite.diff77
-rw-r--r--src/wrap/sqlite/test_sqlite.cpp101
70 files changed, 1335 insertions, 265 deletions
diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp
index 38c6387e5..ad8b1215f 100644
--- a/src/algo_factory/algo_factory.cpp
+++ b/src/algo_factory/algo_factory.cpp
@@ -70,8 +70,7 @@ const T* factory_prototype(const std::string& algo_spec,
{
if(provider == "" || engines[i]->provider_name() == provider)
{
- T* impl = engine_get_algo<T>(engines[i], scan_name, af);
- if(impl)
+ if(T* impl = engine_get_algo<T>(engines[i], scan_name, af))
cache->add(impl, algo_spec, engines[i]->provider_name());
}
}
diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index b34bf8ca2..66a27dd4e 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -7,7 +7,7 @@
#include <botan/ber_dec.h>
#include <botan/bigint.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/asn1/der_enc.cpp b/src/asn1/der_enc.cpp
index 3c318c291..e410292bb 100644
--- a/src/asn1/der_enc.cpp
+++ b/src/asn1/der_enc.cpp
@@ -8,9 +8,9 @@
#include <botan/der_enc.h>
#include <botan/asn1_int.h>
#include <botan/bigint.h>
-#include <botan/loadstor.h>
-#include <botan/internal/bit_ops.h>
+#include <botan/get_byte.h>
#include <botan/parsing.h>
+#include <botan/internal/bit_ops.h>
#include <algorithm>
namespace Botan {
diff --git a/src/block/idea_sse2/idea_sse2.cpp b/src/block/idea_sse2/idea_sse2.cpp
index c00d13ee9..0fe35112d 100644
--- a/src/block/idea_sse2/idea_sse2.cpp
+++ b/src/block/idea_sse2/idea_sse2.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/idea_sse2.h>
-#include <botan/loadstor.h>
#include <emmintrin.h>
namespace Botan {
diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h
index 4532c1be2..22ef65342 100644
--- a/src/block/noekeon/noekeon.h
+++ b/src/block/noekeon/noekeon.h
@@ -26,7 +26,7 @@ class BOTAN_DLL Noekeon : public BlockCipher
BlockCipher* clone() const { return new Noekeon; }
Noekeon() : BlockCipher(16, 16) {}
- private:
+ protected:
void key_schedule(const byte[], u32bit);
static const byte RC[17];
diff --git a/src/block/noekeon_simd/info.txt b/src/block/noekeon_simd/info.txt
new file mode 100644
index 000000000..b73954cff
--- /dev/null
+++ b/src/block/noekeon_simd/info.txt
@@ -0,0 +1,7 @@
+define NOEKEON_SIMD
+
+<requires>
+noekeon
+simd_32
+simd_engine
+</requires>
diff --git a/src/block/noekeon_simd/noekeon_simd.cpp b/src/block/noekeon_simd/noekeon_simd.cpp
new file mode 100644
index 000000000..f44104901
--- /dev/null
+++ b/src/block/noekeon_simd/noekeon_simd.cpp
@@ -0,0 +1,161 @@
+/*
+* Noekeon in SIMD
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/noekeon_simd.h>
+#include <botan/internal/simd_32.h>
+
+namespace Botan {
+
+/*
+* Noekeon's Theta Operation
+*/
+#define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3) \
+ do { \
+ SIMD_32 T = A0 ^ A2; \
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ A1 ^= T; \
+ A3 ^= T; \
+ \
+ A0 ^= K0; \
+ A1 ^= K1; \
+ A2 ^= K2; \
+ A3 ^= K3; \
+ \
+ T = A1 ^ A3; \
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ A0 ^= T; \
+ A2 ^= T; \
+ } while(0)
+
+/*
+* Noekeon's Gamma S-Box Layer
+*/
+#define NOK_SIMD_GAMMA(A0, A1, A2, A3) \
+ do \
+ { \
+ A1 ^= A3.andc(~A2); \
+ A0 ^= A2 & A1; \
+ \
+ SIMD_32 T = A3; \
+ A3 = A0; \
+ A0 = T; \
+ \
+ A2 ^= A0 ^ A1 ^ A3; \
+ \
+ A1 ^= A3.andc(~A2); \
+ A0 ^= A2 & A1; \
+ } while(0)
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], u32bit blocks) const
+ {
+ SIMD_32 K0 = SIMD_32(EK[0]);
+ SIMD_32 K1 = SIMD_32(EK[1]);
+ SIMD_32 K2 = SIMD_32(EK[2]);
+ SIMD_32 K3 = SIMD_32(EK[3]);
+
+ while(blocks >= 4)
+ {
+ SIMD_32 A0 = SIMD_32::load_be(in );
+ SIMD_32 A1 = SIMD_32::load_be(in + 16);
+ SIMD_32 A2 = SIMD_32::load_be(in + 32);
+ SIMD_32 A3 = SIMD_32::load_be(in + 48);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ for(u32bit i = 0; i != 16; ++i)
+ {
+ A0 ^= SIMD_32(RC[i]);
+
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ A1.rotate_left(1);
+ A2.rotate_left(5);
+ A3.rotate_left(2);
+
+ NOK_SIMD_GAMMA(A0, A1, A2, A3);
+
+ A1.rotate_right(1);
+ A2.rotate_right(5);
+ A3.rotate_right(2);
+ }
+
+ A0 ^= SIMD_32(RC[16]);
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ A0.store_be(out);
+ A1.store_be(out + 16);
+ A2.store_be(out + 32);
+ A3.store_be(out + 48);
+
+ in += 64;
+ out += 64;
+ blocks -= 4;
+ }
+
+ Noekeon::encrypt_n(in, out, blocks);
+ }
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], u32bit blocks) const
+ {
+ SIMD_32 K0 = SIMD_32(DK[0]);
+ SIMD_32 K1 = SIMD_32(DK[1]);
+ SIMD_32 K2 = SIMD_32(DK[2]);
+ SIMD_32 K3 = SIMD_32(DK[3]);
+
+ while(blocks >= 4)
+ {
+ SIMD_32 A0 = SIMD_32::load_be(in );
+ SIMD_32 A1 = SIMD_32::load_be(in + 16);
+ SIMD_32 A2 = SIMD_32::load_be(in + 32);
+ SIMD_32 A3 = SIMD_32::load_be(in + 48);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ for(u32bit i = 0; i != 16; ++i)
+ {
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ A0 ^= SIMD_32(RC[16-i]);
+
+ A1.rotate_left(1);
+ A2.rotate_left(5);
+ A3.rotate_left(2);
+
+ NOK_SIMD_GAMMA(A0, A1, A2, A3);
+
+ A1.rotate_right(1);
+ A2.rotate_right(5);
+ A3.rotate_right(2);
+ }
+
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+ A0 ^= SIMD_32(RC[0]);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ A0.store_be(out);
+ A1.store_be(out + 16);
+ A2.store_be(out + 32);
+ A3.store_be(out + 48);
+
+ in += 64;
+ out += 64;
+ blocks -= 4;
+ }
+
+ Noekeon::decrypt_n(in, out, blocks);
+ }
+
+}
diff --git a/src/block/noekeon_simd/noekeon_simd.h b/src/block/noekeon_simd/noekeon_simd.h
new file mode 100644
index 000000000..466c4b741
--- /dev/null
+++ b/src/block/noekeon_simd/noekeon_simd.h
@@ -0,0 +1,29 @@
+/*
+* Noekeon in SIMD
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOEKEON_SIMD_H__
+#define BOTAN_NOEKEON_SIMD_H__
+
+#include <botan/noekeon.h>
+
+namespace Botan {
+
+/*
+* Noekeon
+*/
+class BOTAN_DLL Noekeon_SIMD : public Noekeon
+ {
+ public:
+ void encrypt_n(const byte in[], byte out[], u32bit blocks) const;
+ void decrypt_n(const byte in[], byte out[], u32bit blocks) const;
+
+ BlockCipher* clone() const { return new Noekeon_SIMD; }
+ };
+
+}
+
+#endif
diff --git a/src/build-data/makefile/nmake.in b/src/build-data/makefile/nmake.in
index 79b80745c..2d89850fd 100644
--- a/src/build-data/makefile/nmake.in
+++ b/src/build-data/makefile/nmake.in
@@ -17,7 +17,7 @@ DESTDIR = %{prefix}
LIBDIR = $(DESTDIR)\%{libdir}
HEADERDIR = $(DESTDIR)\%{includedir}\botan
-DOCDIR = $(DESTDIR)\%{docdir}\Botan-$(VERSION)
+DOCDIR = $(DESTDIR)\%{docdir}\botan-$(VERSION)
### Aliases for Common Programs
AR = %{ar_command}
diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in
index a39a10907..c525aa6bf 100644
--- a/src/build-data/makefile/unix.in
+++ b/src/build-data/makefile/unix.in
@@ -16,7 +16,7 @@ DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
HEADERDIR = $(DESTDIR)/%{includedir}/botan
-DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
CONFIG_SCRIPT = %{botan_config}
diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in
index db445163e..aaedeeaf8 100644
--- a/src/build-data/makefile/unix_shr.in
+++ b/src/build-data/makefile/unix_shr.in
@@ -19,7 +19,7 @@ DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
HEADERDIR = $(DESTDIR)/%{includedir}/botan
-DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
CONFIG_SCRIPT = %{botan_config}
diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp
index 98e74a6b0..06b7eb1ab 100644
--- a/src/cert/cvc/cvc_self.cpp
+++ b/src/cert/cvc/cvc_self.cpp
@@ -80,7 +80,7 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
ASN1_Chr chr(opt.car.value());
AlgorithmIdentifier sig_algo;
- std::string padding_and_hash(eac_cvc_emsa + "(" + opt.hash_alg + ")");
+ std::string padding_and_hash("EMSA1_BSI(" + opt.hash_alg + ")");
sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
@@ -109,7 +109,7 @@ EAC1_1_Req create_cvc_req(Private_Key const& key,
throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
}
AlgorithmIdentifier sig_algo;
- std::string padding_and_hash(eac_cvc_emsa + "(" + hash_alg + ")");
+ std::string padding_and_hash("EMSA1_BSI(" + hash_alg + ")");
sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h
index d357adb7d..646bbeee6 100644
--- a/src/cert/cvc/eac_obj.h
+++ b/src/cert/cvc/eac_obj.h
@@ -23,8 +23,6 @@
namespace Botan {
-const std::string eac_cvc_emsa("EMSA1_BSI");
-
/*
* TR03110 v1.1 EAC CV Certificate
*/
diff --git a/src/checksum/crc24/crc24.cpp b/src/checksum/crc24/crc24.cpp
index e50b4d33e..5441020f5 100644
--- a/src/checksum/crc24/crc24.cpp
+++ b/src/checksum/crc24/crc24.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/crc24.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp
index 8d2d7257d..5d1e674ca 100644
--- a/src/constructs/aont/package.cpp
+++ b/src/constructs/aont/package.cpp
@@ -9,7 +9,7 @@
#include <botan/package.h>
#include <botan/filters.h>
#include <botan/ctr.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
namespace Botan {
diff --git a/src/constructs/cryptobox/cryptobox.cpp b/src/constructs/cryptobox/cryptobox.cpp
index 20435fa59..371b52e66 100644
--- a/src/constructs/cryptobox/cryptobox.cpp
+++ b/src/constructs/cryptobox/cryptobox.cpp
@@ -13,7 +13,7 @@
#include <botan/hmac.h>
#include <botan/pbkdf2.h>
#include <botan/pem.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/mem_ops.h>
namespace Botan {
@@ -48,10 +48,10 @@ std::string encrypt(const byte input[], u32bit input_len,
rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size());
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
@@ -109,10 +109,10 @@ std::string decrypt(const byte input[], u32bit input_len,
SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN);
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
diff --git a/src/constructs/fpe/fpe.cpp b/src/constructs/fpe/fpe.cpp
index 86e56625d..a0b3274b5 100644
--- a/src/constructs/fpe/fpe.cpp
+++ b/src/constructs/fpe/fpe.cpp
@@ -12,7 +12,7 @@
#include <botan/numthry.h>
#include <botan/hmac.h>
#include <botan/sha2_32.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <stdexcept>
namespace Botan {
diff --git a/src/constructs/passhash/info.txt b/src/constructs/passhash/info.txt
new file mode 100644
index 000000000..f96809f29
--- /dev/null
+++ b/src/constructs/passhash/info.txt
@@ -0,0 +1,9 @@
+define PASSHASH9
+
+<requires>
+libstate
+pbkdf2
+rng
+base64
+</requires>
+
diff --git a/src/constructs/passhash/passhash9.cpp b/src/constructs/passhash/passhash9.cpp
new file mode 100644
index 000000000..9e5ff3257
--- /dev/null
+++ b/src/constructs/passhash/passhash9.cpp
@@ -0,0 +1,127 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/passhash9.h>
+#include <botan/loadstor.h>
+#include <botan/libstate.h>
+#include <botan/pbkdf2.h>
+#include <botan/base64.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+namespace {
+
+const std::string MAGIC_PREFIX = "$9$";
+
+const u32bit WORKFACTOR_BYTES = 2;
+const u32bit ALGID_BYTES = 1;
+const u32bit SALT_BYTES = 12; // 96 bits of salt
+const u32bit PBKDF_OUTPUT_LEN = 24; // 192 bits output
+
+const u32bit WORK_FACTOR_SCALE = 10000;
+
+MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(alg_id == 0)
+ return af.make_mac("HMAC(SHA-1)");
+
+ return 0;
+ }
+
+std::pair<byte, MessageAuthenticationCode*> choose_pbkdf_prf()
+ {
+ byte alg_id = 0;
+ return std::make_pair(alg_id, get_pbkdf_prf(alg_id));
+ }
+
+}
+
+std::string generate_passhash9(const std::string& pass,
+ RandomNumberGenerator& rng,
+ u16bit work_factor)
+ {
+ std::pair<byte, MessageAuthenticationCode*> prf = choose_pbkdf_prf();
+ byte alg_id = prf.first;
+
+ PKCS5_PBKDF2 kdf(prf.second); // takes ownership of pointer
+
+ SecureVector<byte> salt(SALT_BYTES);
+ rng.randomize(&salt[0], salt.size());
+
+ u32bit kdf_iterations = WORK_FACTOR_SCALE * work_factor;
+
+ SecureVector<byte> pbkdf2_output =
+ kdf.derive_key(PBKDF_OUTPUT_LEN, pass,
+ &salt[0], salt.size(),
+ kdf_iterations).bits_of();
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.start_msg();
+ pipe.write(alg_id);
+ pipe.write(get_byte(0, work_factor));
+ pipe.write(get_byte(1, work_factor));
+ pipe.write(salt);
+ pipe.write(pbkdf2_output);
+ pipe.end_msg();
+
+ return MAGIC_PREFIX + pipe.read_all_as_string();
+ }
+
+bool check_passhash9(const std::string& pass, const std::string& hash)
+ {
+ const u32bit BINARY_LENGTH =
+ (ALGID_BYTES + WORKFACTOR_BYTES + PBKDF_OUTPUT_LEN + SALT_BYTES);
+
+ const u32bit BASE64_LENGTH =
+ MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;
+
+ if(hash.size() != BASE64_LENGTH)
+ return false;
+
+ for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
+ if(hash[i] != MAGIC_PREFIX[i])
+ return false;
+
+ Pipe pipe(new Base64_Decoder);
+ pipe.start_msg();
+ pipe.write(hash.c_str() + MAGIC_PREFIX.size());
+ pipe.end_msg();
+
+ SecureVector<byte> bin = pipe.read_all();
+
+ if(bin.size() != BINARY_LENGTH)
+ return false;
+
+ byte alg_id = bin[0];
+
+ u32bit kdf_iterations =
+ WORK_FACTOR_SCALE * load_be<u16bit>(bin + ALGID_BYTES, 0);
+
+ if(kdf_iterations == 0)
+ return false;
+
+ MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);
+
+ if(pbkdf_prf == 0)
+ return false; // unknown algorithm, reject
+
+ PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer
+
+ SecureVector<byte> cmp = kdf.derive_key(
+ PBKDF_OUTPUT_LEN, pass,
+ &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
+ kdf_iterations).bits_of();
+
+ return same_mem(cmp.begin(),
+ bin.begin() + ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES,
+ PBKDF_OUTPUT_LEN);
+ }
+
+}
diff --git a/src/constructs/passhash/passhash9.h b/src/constructs/passhash/passhash9.h
new file mode 100644
index 000000000..6020dce42
--- /dev/null
+++ b/src/constructs/passhash/passhash9.h
@@ -0,0 +1,35 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PASSHASH9_H__
+#define BOTAN_PASSHASH9_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Create a password hash using PBKDF2
+* @param password the password
+* @param rng a random number generator
+* @Param work_factor how much work to do to slow down guessing attacks
+*/
+std::string BOTAN_DLL generate_passhash9(const std::string& password,
+ RandomNumberGenerator& rng,
+ u16bit work_factor = 10);
+
+/**
+* Check a previously created password hash
+* @param password the password to check against
+* @param hash the stored hash to check against
+*/
+bool BOTAN_DLL check_passhash9(const std::string& password,
+ const std::string& hash);
+
+}
+
+#endif
diff --git a/src/engine/gnump/gmp_mem.cpp b/src/engine/gnump/gmp_mem.cpp
index 59e0cc4c5..f3650e716 100644
--- a/src/engine/gnump/gmp_mem.cpp
+++ b/src/engine/gnump/gmp_mem.cpp
@@ -1,6 +1,6 @@
/*
* GNU MP Memory Handlers
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -17,6 +17,7 @@ namespace {
* Allocator used by GNU MP
*/
Allocator* gmp_alloc = 0;
+u32bit gmp_alloc_refcnt = 0;
/*
* Allocation Function for GNU MP
@@ -48,23 +49,28 @@ void gmp_free(void* ptr, size_t n)
}
/*
-* Set the GNU MP memory functions
+* GMP_Engine Constructor
*/
-void GMP_Engine::set_memory_hooks()
+GMP_Engine::GMP_Engine()
{
if(gmp_alloc == 0)
{
gmp_alloc = Allocator::get(true);
mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
}
+
+ ++gmp_alloc_refcnt;
}
-/*
-* GMP_Engine Constructor
-*/
-GMP_Engine::GMP_Engine()
+GMP_Engine::~GMP_Engine()
{
- set_memory_hooks();
+ --gmp_alloc_refcnt;
+
+ if(gmp_alloc_refcnt == 0)
+ {
+ mp_set_memory_functions(NULL, NULL, NULL);
+ gmp_alloc = 0;
+ }
}
}
diff --git a/src/engine/gnump/gnump_engine.h b/src/engine/gnump/gnump_engine.h
index ec4a7e721..d0b070441 100644
--- a/src/engine/gnump/gnump_engine.h
+++ b/src/engine/gnump/gnump_engine.h
@@ -18,6 +18,9 @@ namespace Botan {
class GMP_Engine : public Engine
{
public:
+ GMP_Engine();
+ ~GMP_Engine();
+
std::string provider_name() const { return "gmp"; }
#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
@@ -46,10 +49,6 @@ class GMP_Engine : public Engine
Modular_Exponentiator* mod_exp(const BigInt&,
Power_Mod::Usage_Hints) const;
-
- GMP_Engine();
- private:
- static void set_memory_hooks();
};
}
diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp
index b8ebd6a80..e889ca161 100644
--- a/src/engine/simd_engine/simd_engine.cpp
+++ b/src/engine/simd_engine/simd_engine.cpp
@@ -13,6 +13,10 @@
#include <botan/serp_simd.h>
#endif
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ #include <botan/noekeon_simd.h>
+#endif
+
#if defined(BOTAN_HAS_XTEA_SIMD)
#include <botan/xtea_simd.h>
#endif
@@ -36,6 +40,11 @@ SIMD_Engine::find_block_cipher(const SCAN_Name& request,
return new IDEA_SSE2;
#endif
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(request.algo_name() == "Noekeon" && SIMD_32::enabled())
+ return new Noekeon_SIMD;
+#endif
+
#if defined(BOTAN_HAS_SERPENT_SIMD)
if(request.algo_name() == "Serpent" && SIMD_32::enabled())
return new Serpent_SIMD;
diff --git a/src/filters/buf_filt.cpp b/src/filters/buf_filt.cpp
index 97dd1b890..9b4f4af88 100644
--- a/src/filters/buf_filt.cpp
+++ b/src/filters/buf_filt.cpp
@@ -12,14 +12,6 @@
namespace Botan {
-namespace {
-
-const size_t BUFFER_MULTIPLE = 2;
-
-//static_assert(BUFFER_MULTIPLE >= 2, "BUFFER_MULTIPLE must be >= 2");
-
-}
-
/*
* Buffered_Filter Constructor
*/
@@ -32,7 +24,7 @@ Buffered_Filter::Buffered_Filter(u32bit b, u32bit f) :
if(final_minimum > main_block_mod)
throw std::invalid_argument("final_minimum > main_block_mod");
- buffer.resize(BUFFER_MULTIPLE * main_block_mod);
+ buffer.resize(2 * main_block_mod);
buffer_pos = 0;
}
@@ -54,23 +46,22 @@ void Buffered_Filter::write(const byte input[], u32bit input_size)
input += to_copy;
input_size -= to_copy;
- if(input_size >= final_minimum)
- {
- u32bit to_proc_blocks = buffer_pos / main_block_mod;
- u32bit to_proc_bytes = to_proc_blocks * main_block_mod;
+ u32bit total_to_consume =
+ round_down(std::min(buffer_pos,
+ buffer_pos + input_size - final_minimum),
+ main_block_mod);
- buffered_block(&buffer[0], to_proc_bytes);
+ buffered_block(&buffer[0], total_to_consume);
- buffer_pos -= to_proc_bytes;
+ buffer_pos -= total_to_consume;
- copy_mem(&buffer[0], &buffer[to_proc_bytes], buffer_pos);
- }
+ copy_mem(&buffer[0], &buffer[total_to_consume], buffer_pos);
}
if(input_size >= final_minimum)
{
- u32bit full_blocks = (input_size - final_minimum) / buffer.size();
- u32bit to_copy = full_blocks * buffer.size();
+ u32bit full_blocks = (input_size - final_minimum) / main_block_mod;
+ u32bit to_copy = full_blocks * main_block_mod;
if(to_copy)
{
diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h
index b303a841f..6d9092041 100644
--- a/src/filters/modes/cbc/cbc.h
+++ b/src/filters/modes/cbc/cbc.h
@@ -39,7 +39,7 @@ class BOTAN_DLL CBC_Encryption : public Keyed_Filter,
const SymmetricKey& key,
const InitializationVector& iv);
- ~CBC_Encryption() { delete padder; }
+ ~CBC_Encryption() { delete cipher; delete padder; }
private:
void buffered_block(const byte input[], u32bit input_length);
void buffered_final(const byte input[], u32bit input_length);
@@ -76,7 +76,7 @@ class BOTAN_DLL CBC_Decryption : public Keyed_Filter,
const SymmetricKey& key,
const InitializationVector& iv);
- ~CBC_Decryption() { delete padder; }
+ ~CBC_Decryption() { delete cipher; delete padder; }
private:
void buffered_block(const byte input[], u32bit input_length);
void buffered_final(const byte input[], u32bit input_length);
diff --git a/src/filters/modes/cfb/cfb.h b/src/filters/modes/cfb/cfb.h
index 917125e46..249ae21db 100644
--- a/src/filters/modes/cfb/cfb.h
+++ b/src/filters/modes/cfb/cfb.h
@@ -34,6 +34,8 @@ class BOTAN_DLL CFB_Encryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv,
u32bit feedback = 0);
+
+ ~CFB_Encryption() { delete cipher; }
private:
void write(const byte[], u32bit);
@@ -63,6 +65,8 @@ class BOTAN_DLL CFB_Decryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv,
u32bit feedback = 0);
+
+ ~CFB_Decryption() { delete cipher; }
private:
void write(const byte[], u32bit);
diff --git a/src/filters/modes/cts/cts.h b/src/filters/modes/cts/cts.h
index 4a7513fa0..c15fa9510 100644
--- a/src/filters/modes/cts/cts.h
+++ b/src/filters/modes/cts/cts.h
@@ -33,6 +33,8 @@ class BOTAN_DLL CTS_Encryption : public Keyed_Filter
CTS_Encryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~CTS_Encryption() { delete cipher; }
private:
void write(const byte[], u32bit);
void end_msg();
@@ -63,6 +65,8 @@ class BOTAN_DLL CTS_Decryption : public Keyed_Filter
CTS_Decryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~CTS_Decryption() { delete cipher; }
private:
void write(const byte[], u32bit);
void end_msg();
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp
index cfea0b34b..aeef4e88d 100644
--- a/src/filters/modes/xts/xts.cpp
+++ b/src/filters/modes/xts/xts.cpp
@@ -176,6 +176,15 @@ void XTS_Encryption::buffered_final(const byte input[], u32bit length)
}
else
{ // steal ciphertext
+
+ u32bit leftover_blocks =
+ ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE;
+
+ buffered_block(input, leftover_blocks);
+
+ input += leftover_blocks;
+ length -= leftover_blocks;
+
SecureVector<byte> temp(input, length);
xor_buf(temp, tweak, cipher->BLOCK_SIZE);
@@ -201,9 +210,13 @@ void XTS_Encryption::buffered_final(const byte input[], u32bit length)
* XTS_Decryption constructor
*/
XTS_Decryption::XTS_Decryption(BlockCipher* ciph) :
- Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- cipher = ciph;
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
cipher2 = ciph->clone();
tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
}
@@ -214,9 +227,13 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) :
XTS_Decryption::XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv) :
- Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE, 1)
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- cipher = ciph;
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
cipher2 = ciph->clone();
tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
@@ -320,18 +337,26 @@ void XTS_Decryption::buffered_block(const byte input[], u32bit input_length)
}
}
-void XTS_Decryption::buffered_final(const byte input[], u32bit input_length)
+void XTS_Decryption::buffered_final(const byte input[], u32bit length)
{
- if(input_length <= cipher->BLOCK_SIZE)
+ if(length <= cipher->BLOCK_SIZE)
throw Decoding_Error("XTS_Decryption: insufficient data to decrypt");
- if(input_length % cipher->BLOCK_SIZE == 0)
+ if(length % cipher->BLOCK_SIZE == 0)
{
- buffered_block(input, input_length);
+ buffered_block(input, length);
}
else
{
- SecureVector<byte> temp(input, input_length);
+ u32bit leftover_blocks =
+ ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE;
+
+ buffered_block(input, leftover_blocks);
+
+ input += leftover_blocks;
+ length -= leftover_blocks;
+
+ SecureVector<byte> temp(input, length);
SecureVector<byte> tweak_copy(&tweak[0], cipher->BLOCK_SIZE);
poly_double(tweak_copy, cipher->BLOCK_SIZE);
@@ -340,14 +365,14 @@ void XTS_Decryption::buffered_final(const byte input[], u32bit input_length)
cipher->decrypt(temp);
xor_buf(temp, tweak_copy, cipher->BLOCK_SIZE);
- for(u32bit i = 0; i != input_length - cipher->BLOCK_SIZE; ++i)
+ for(u32bit i = 0; i != length - cipher->BLOCK_SIZE; ++i)
std::swap(temp[i], temp[i + cipher->BLOCK_SIZE]);
xor_buf(temp, tweak, cipher->BLOCK_SIZE);
cipher->decrypt(temp);
xor_buf(temp, tweak, cipher->BLOCK_SIZE);
- send(temp, input_length);
+ send(temp, length);
}
buffer_reset();
diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h
index 724085d9d..a01b1da1d 100644
--- a/src/filters/modes/xts/xts.h
+++ b/src/filters/modes/xts/xts.h
@@ -68,6 +68,8 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter,
XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~XTS_Decryption() { delete cipher; delete cipher2; }
private:
void write(const byte[], u32bit);
void end_msg();
diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h
index 0b76a70e4..0bff5a4ce 100644
--- a/src/hash/md4/md4.h
+++ b/src/hash/md4/md4.h
@@ -27,7 +27,7 @@ class BOTAN_DLL MD4 : public MDx_HashFunction
void hash_old(const byte[]);
void copy_out(byte[]);
- SecureBuffer<u32bit, 48> M;
+ SecureBuffer<u32bit, 16> M;
SecureBuffer<u32bit, 4> digest;
};
diff --git a/src/hash/md4_ia32/md4_ia32.cpp b/src/hash/md4_ia32/md4_ia32.cpp
index 12fe71da4..8a60d8f0e 100644
--- a/src/hash/md4_ia32/md4_ia32.cpp
+++ b/src/hash/md4_ia32/md4_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/md4_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/hash/md5_ia32/md5_ia32.cpp b/src/hash/md5_ia32/md5_ia32.cpp
index 443569b3b..affd0b8f7 100644
--- a/src/hash/md5_ia32/md5_ia32.cpp
+++ b/src/hash/md5_ia32/md5_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/md5_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/hash/sha1/sha160.cpp b/src/hash/sha1/sha160.cpp
index ff44593f6..1ad08d483 100644
--- a/src/hash/sha1/sha160.cpp
+++ b/src/hash/sha1/sha160.cpp
@@ -134,8 +134,8 @@ void SHA_160::compress_n(const byte input[], u32bit blocks)
*/
void SHA_160::copy_out(byte output[])
{
- for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
- store_be(digest[j/4], output + j);
+ for(u32bit i = 0; i != OUTPUT_LENGTH; i += 4)
+ store_be(digest[i/4], output + i);
}
/*
diff --git a/src/hash/sha1_ia32/sha1_ia32.cpp b/src/hash/sha1_ia32/sha1_ia32.cpp
index 0fa0b6bf2..6eecdab56 100644
--- a/src/hash/sha1_ia32/sha1_ia32.cpp
+++ b/src/hash/sha1_ia32/sha1_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/sha1_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/kdf/kdf2/kdf2.cpp b/src/kdf/kdf2/kdf2.cpp
index 167f64436..7cc1d7416 100644
--- a/src/kdf/kdf2/kdf2.cpp
+++ b/src/kdf/kdf2/kdf2.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/kdf2.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/kdf/mgf1/mgf1.cpp b/src/kdf/mgf1/mgf1.cpp
index a8c7e5fa3..340e87a7c 100644
--- a/src/kdf/mgf1/mgf1.cpp
+++ b/src/kdf/mgf1/mgf1.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/mgf1.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/exceptn.h>
#include <botan/internal/xor_buf.h>
#include <algorithm>
diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp
index 4f5884630..c11fc28ce 100644
--- a/src/libstate/policy.cpp
+++ b/src/libstate/policy.cpp
@@ -48,6 +48,7 @@ void set_default_oids(Library_State& config)
add_oid(config, "2.16.840.1.101.3.4.1.22", "AES-192/CBC");
add_oid(config, "2.16.840.1.101.3.4.1.42", "AES-256/CBC");
add_oid(config, "1.2.410.200004.1.4", "SEED/CBC"); // RFC 4010
+ add_oid(config, "1.3.6.1.4.1.25258.3.1", "Serpent/CBC");
/* Hash Functions */
add_oid(config, "1.2.840.113549.2.5", "MD5");
diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp
index 861934200..eccb15565 100644
--- a/src/libstate/scan_name.cpp
+++ b/src/libstate/scan_name.cpp
@@ -63,7 +63,7 @@ deref_aliases(const std::pair<u32bit, std::string>& in)
}
-SCAN_Name::SCAN_Name(const std::string& algo_spec)
+SCAN_Name::SCAN_Name(std::string algo_spec)
{
orig_algo_spec = algo_spec;
@@ -73,6 +73,8 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec)
std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
+ algo_spec = global_state().deref_alias(algo_spec);
+
for(u32bit i = 0; i != algo_spec.size(); ++i)
{
char c = algo_spec[i];
diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h
index 7992d7498..4350dca86 100644
--- a/src/libstate/scan_name.h
+++ b/src/libstate/scan_name.h
@@ -23,9 +23,9 @@ class BOTAN_DLL SCAN_Name
{
public:
/**
- @param algo_spec A SCAN name
+ @param algo_spec A SCAN-format name
*/
- SCAN_Name(const std::string& algo_spec);
+ SCAN_Name(std::string algo_spec);
/**
@return the original input string
diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp
index 70bb11a83..09ac2a75d 100644
--- a/src/math/bigint/bigint.cpp
+++ b/src/math/bigint/bigint.cpp
@@ -7,7 +7,7 @@
#include <botan/bigint.h>
#include <botan/internal/mp_core.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/parsing.h>
#include <botan/internal/rounding.h>
diff --git a/src/pbe/pbes1/pbes1.cpp b/src/pbe/pbes1/pbes1.cpp
index 1d851d1a5..36cfaa6b4 100644
--- a/src/pbe/pbes1/pbes1.cpp
+++ b/src/pbe/pbes1/pbes1.cpp
@@ -80,9 +80,9 @@ void PBE_PKCS5v15::set_key(const std::string& passphrase)
{
PKCS5_PBKDF1 pbkdf(hash_function->clone());
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase);
+ SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase,
+ &salt[0], salt.size(),
+ iterations);
key.set(key_and_iv.begin(), 8);
iv.set(key_and_iv.begin() + 8, 8);
diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp
index bd24c449b..63772263f 100644
--- a/src/pbe/pbes2/pbes2.cpp
+++ b/src/pbe/pbes2/pbes2.cpp
@@ -87,9 +87,9 @@ void PBE_PKCS5v20::set_key(const std::string& passphrase)
{
PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone()));
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- key = pbkdf.derive_key(key_length, passphrase).bits_of();
+ key = pbkdf.derive_key(key_length, passphrase,
+ &salt[0], salt.size(),
+ iterations).bits_of();
}
/**
diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp
index 995ec9259..84a7b1c13 100644
--- a/src/rng/hmac_rng/hmac_rng.cpp
+++ b/src/rng/hmac_rng/hmac_rng.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/hmac_rng.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
#include <botan/internal/stl_util.h>
#include <algorithm>
diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp
index f6479b2dd..9a4d77e55 100644
--- a/src/rng/randpool/randpool.cpp
+++ b/src/rng/randpool/randpool.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/randpool.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
#include <botan/internal/stl_util.h>
#include <algorithm>
diff --git a/src/s2k/info.txt b/src/s2k/info.txt
index 1d5226524..861b6f760 100644
--- a/src/s2k/info.txt
+++ b/src/s2k/info.txt
@@ -1,4 +1,3 @@
<requires>
-rng
sym_algo
</requires>
diff --git a/src/s2k/pbkdf1/pbkdf1.cpp b/src/s2k/pbkdf1/pbkdf1.cpp
index fcc5b9a97..a8270e26f 100644
--- a/src/s2k/pbkdf1/pbkdf1.cpp
+++ b/src/s2k/pbkdf1/pbkdf1.cpp
@@ -6,16 +6,17 @@
*/
#include <botan/pbkdf1.h>
+#include <botan/exceptn.h>
namespace Botan {
/*
* Return a PKCS#5 PBKDF1 derived key
*/
-OctetString PKCS5_PBKDF1::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF1::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
throw Invalid_Argument("PKCS5_PBKDF1: Invalid iteration count");
diff --git a/src/s2k/pbkdf1/pbkdf1.h b/src/s2k/pbkdf1/pbkdf1.h
index 4e5cafdb0..053a2dbe1 100644
--- a/src/s2k/pbkdf1/pbkdf1.h
+++ b/src/s2k/pbkdf1/pbkdf1.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified hash function.
* @param hash a pointer to a hash function object to use
@@ -33,9 +38,6 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
~PKCS5_PBKDF1() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/pbkdf2/pbkdf2.cpp b/src/s2k/pbkdf2/pbkdf2.cpp
index 6f790c06b..f1fc6e29f 100644
--- a/src/s2k/pbkdf2/pbkdf2.cpp
+++ b/src/s2k/pbkdf2/pbkdf2.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/pbkdf2.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
namespace Botan {
@@ -14,10 +14,10 @@ namespace Botan {
/*
* Return a PKCS#5 PBKDF2 derived key
*/
-OctetString PKCS5_PBKDF2::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF2::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count");
diff --git a/src/s2k/pbkdf2/pbkdf2.h b/src/s2k/pbkdf2/pbkdf2.h
index 7510338bb..b6d231916 100644
--- a/src/s2k/pbkdf2/pbkdf2.h
+++ b/src/s2k/pbkdf2/pbkdf2.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified message auth code
* @param mac the MAC to use
@@ -29,9 +34,6 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
PKCS5_PBKDF2(MessageAuthenticationCode* mac);
~PKCS5_PBKDF2();
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
MessageAuthenticationCode* mac;
};
diff --git a/src/s2k/pgps2k/pgp_s2k.cpp b/src/s2k/pgps2k/pgp_s2k.cpp
index 86394d84d..49ff6892c 100644
--- a/src/s2k/pgps2k/pgp_s2k.cpp
+++ b/src/s2k/pgps2k/pgp_s2k.cpp
@@ -14,9 +14,10 @@ namespace Botan {
/*
* Derive a key using the OpenPGP S2K algorithm
*/
-OctetString OpenPGP_S2K::derive(u32bit key_len, const std::string& passphrase,
- const byte salt_buf[], u32bit salt_size,
- u32bit iterations) const
+OctetString OpenPGP_S2K::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt_buf[], u32bit salt_size,
+ u32bit iterations) const
{
SecureVector<byte> key(key_len), hash_buf;
diff --git a/src/s2k/pgps2k/pgp_s2k.h b/src/s2k/pgps2k/pgp_s2k.h
index 00e95f7fa..7f25623f3 100644
--- a/src/s2k/pgps2k/pgp_s2k.h
+++ b/src/s2k/pgps2k/pgp_s2k.h
@@ -22,12 +22,14 @@ class BOTAN_DLL OpenPGP_S2K : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
~OpenPGP_S2K() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/s2k.cpp b/src/s2k/s2k.cpp
deleted file mode 100644
index 42064529d..000000000
--- a/src/s2k/s2k.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* S2K
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/s2k.h>
-
-namespace Botan {
-
-/*
-* Derive a key from a passphrase
-*/
-OctetString S2K::derive_key(u32bit key_len,
- const std::string& passphrase) const
- {
- return derive(key_len, passphrase, salt, salt.size(), iterations());
- }
-
-/*
-* Set the number of iterations
-*/
-void S2K::set_iterations(u32bit i)
- {
- iter = i;
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const byte new_salt[], u32bit length)
- {
- salt.set(new_salt, length);
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const MemoryRegion<byte>& new_salt)
- {
- change_salt(new_salt.begin(), new_salt.size());
- }
-
-/*
-* Create a new random salt
-*/
-void S2K::new_random_salt(RandomNumberGenerator& rng,
- u32bit length)
- {
- salt.resize(length);
- rng.randomize(salt, length);
- }
-
-}
diff --git a/src/s2k/s2k.h b/src/s2k/s2k.h
index 7af92519b..9ab71344e 100644
--- a/src/s2k/s2k.h
+++ b/src/s2k/s2k.h
@@ -9,7 +9,6 @@
#define BOTAN_S2K_H__
#include <botan/symkey.h>
-#include <botan/rng.h>
namespace Botan {
@@ -39,62 +38,22 @@ class BOTAN_DLL S2K
/**
* Derive a key from a passphrase with this S2K object. It will use
* the salt value and number of iterations configured in this object.
- * @param key_len the desired length of the key to produce
+ * @param output_len the desired length of the key to produce
* @param passphrase the password to derive the key from
+ * @param salt the randomly chosen salt
+ * @param salt_len length of salt in bytes
+ * @param iterations the number of iterations to use (use 10K or more)
*/
- OctetString derive_key(u32bit key_len,
- const std::string& passphrase) const;
+ virtual OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const = 0;
- /**
- * Set the number of iterations for the one-way function during
- * key generation.
- * @param n the desired number of iterations
- */
- void set_iterations(u32bit n);
-
- /**
- * Set a new salt value.
- * @param new_salt a byte array defining the new salt value
- * @param len the length of the above byte array
- */
- void change_salt(const byte new_salt[], u32bit len);
-
- /**
- * Set a new salt value.
- * @param new_salt the new salt value
- */
- void change_salt(const MemoryRegion<byte>& new_salt);
-
- /**
- * Create a new random salt value using the rng
- * @param rng the random number generator to use
- * @param len the desired length of the new salt value
- */
- void new_random_salt(RandomNumberGenerator& rng, u32bit len);
-
- /**
- * Get the number of iterations for the key derivation currently
- * configured in this S2K object.
- * @return the current number of iterations
- */
- u32bit iterations() const { return iter; }
-
- /**
- * Get the currently configured salt value of this S2K object.
- * @return the current salt value
- */
- SecureVector<byte> current_salt() const { return salt; }
-
- S2K() { iter = 0; }
+ S2K() {}
virtual ~S2K() {}
private:
S2K(const S2K&) {}
S2K& operator=(const S2K&) { return (*this); }
-
- virtual OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const = 0;
- SecureVector<byte> salt;
- u32bit iter;
};
}
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
index 924d29b1b..8d801b75f 100644
--- a/src/utils/cpuid.cpp
+++ b/src/utils/cpuid.cpp
@@ -7,7 +7,7 @@
#include <botan/cpuid.h>
#include <botan/types.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/mem_ops.h>
#if defined(BOTAN_TARGET_OS_IS_DARWIN)
diff --git a/src/utils/debug.cpp b/src/utils/debug.cpp
deleted file mode 100644
index 894418650..000000000
--- a/src/utils/debug.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
-* Internal-use debugging functions for Botan
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/debug.h>
-#include <cstdio>
-
-namespace Botan {
-
-namespace Debug {
-
-void print_vec(const std::string& name,
- const byte array[],
- size_t array_len)
- {
- std::printf("%s = ", name.c_str());
- for(size_t i = 0; i != array_len; ++i)
- std::printf("%02X", array[i]);
- std::printf("\n");
- }
-
-void print_vec(const std::string& name,
- const MemoryRegion<byte>& vec)
- {
- print_vec(name, &vec[0], vec.size());
- }
-
-}
-
-}
diff --git a/src/utils/debug.h b/src/utils/debug.h
index ee93d5ea0..c7f19c1b1 100644
--- a/src/utils/debug.h
+++ b/src/utils/debug.h
@@ -9,18 +9,29 @@
#define BOTAN_DEBUG_H__
#include <botan/secmem.h>
+#include <iostream>
namespace Botan {
namespace Debug {
+template<typename T>
void print_vec(const std::string& name,
- const byte array[],
- size_t array_len);
+ const T array[], size_t array_len)
+ {
+ std::cout << name << " = ";
-void print_vec(const std::string& name,
- const MemoryRegion<byte>& vec);
+ for(size_t i = 0; i != array_len; ++i)
+ std::cout << std::hex << array[i];
+ std::cout << std::endl;
+ }
+template<typename T>
+void print_vec(const std::string& name,
+ const MemoryRegion<T>& vec)
+ {
+ print_vec(name, &vec[0], vec.size());
+ }
}
diff --git a/src/utils/get_byte.h b/src/utils/get_byte.h
new file mode 100644
index 000000000..fce87af83
--- /dev/null
+++ b/src/utils/get_byte.h
@@ -0,0 +1,27 @@
+/*
+* Read out bytes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GET_BYTE_H__
+#define BOTAN_GET_BYTE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Byte Extraction Function
+*/
+template<typename T> inline byte get_byte(u32bit byte_num, T input)
+ {
+ return static_cast<byte>(
+ input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
+ );
+ }
+
+}
+
+#endif
diff --git a/src/utils/info.txt b/src/utils/info.txt
index 9d8f7976e..2fb3e79a5 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -5,7 +5,6 @@ load_on always
<source>
charset.cpp
cpuid.cpp
-debug.cpp
mlock.cpp
parsing.cpp
time.cpp
@@ -36,6 +35,7 @@ time.h
types.h
ui.h
version.h
+get_byte.h
</header:public>
<libs>
diff --git a/src/utils/loadstor.h b/src/utils/loadstor.h
index bd2acc87d..ffd27540d 100644
--- a/src/utils/loadstor.h
+++ b/src/utils/loadstor.h
@@ -11,6 +11,7 @@
#include <botan/types.h>
#include <botan/bswap.h>
+#include <botan/get_byte.h>
#include <cstring>
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
@@ -38,16 +39,6 @@
namespace Botan {
/*
-* Byte Extraction Function
-*/
-template<typename T> inline byte get_byte(u32bit byte_num, T input)
- {
- return static_cast<byte>(
- input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
- );
- }
-
-/*
* Byte to Word Conversions
*/
inline u16bit make_u16bit(byte i0, byte i1)
diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp
index 4b99ac1ec..e8259ac52 100644
--- a/src/utils/parsing.cpp
+++ b/src/utils/parsing.cpp
@@ -8,7 +8,7 @@
#include <botan/parsing.h>
#include <botan/exceptn.h>
#include <botan/charset.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/utils/simd_32/simd_32.h b/src/utils/simd_32/simd_32.h
index 38ea078d0..4bd983f5e 100644
--- a/src/utils/simd_32/simd_32.h
+++ b/src/utils/simd_32/simd_32.h
@@ -27,4 +27,20 @@
#endif
+namespace Botan {
+
+inline SIMD_32 rotate_left(SIMD_32 x, u32bit rot)
+ {
+ x.rotate_left(rot);
+ return x;
+ }
+
+inline SIMD_32 rotate_right(SIMD_32 x, u32bit rot)
+ {
+ x.rotate_right(rot);
+ return x;
+ }
+
+}
+
#endif
diff --git a/src/utils/simd_32/simd_altivec.h b/src/utils/simd_32/simd_altivec.h
index 9cc5c1068..859a48a5f 100644
--- a/src/utils/simd_32/simd_altivec.h
+++ b/src/utils/simd_32/simd_altivec.h
@@ -145,6 +145,11 @@ class SIMD_Altivec
reg = vec_or(reg, other.reg);
}
+ SIMD_Altivec operator&(const SIMD_Altivec& other)
+ {
+ return vec_and(reg, other.reg);
+ }
+
void operator&=(const SIMD_Altivec& other)
{
reg = vec_and(reg, other.reg);
diff --git a/src/utils/simd_32/simd_scalar.h b/src/utils/simd_32/simd_scalar.h
index 148b76c35..5cf1a11c3 100644
--- a/src/utils/simd_32/simd_scalar.h
+++ b/src/utils/simd_32/simd_scalar.h
@@ -142,6 +142,14 @@ class SIMD_Scalar
R3 |= other.R3;
}
+ SIMD_Scalar operator&(const SIMD_Scalar& other)
+ {
+ return SIMD_Scalar(R0 & other.R0,
+ R1 & other.R1,
+ R2 & other.R2,
+ R3 & other.R3);
+ }
+
void operator&=(const SIMD_Scalar& other)
{
R0 &= other.R0;
diff --git a/src/utils/simd_32/simd_sse.h b/src/utils/simd_32/simd_sse.h
index 31bbce2c7..0189c2e4d 100644
--- a/src/utils/simd_32/simd_sse.h
+++ b/src/utils/simd_32/simd_sse.h
@@ -101,6 +101,11 @@ class SIMD_SSE2
reg = _mm_or_si128(reg, other.reg);
}
+ SIMD_SSE2 operator&(const SIMD_SSE2& other)
+ {
+ return _mm_and_si128(reg, other.reg);
+ }
+
void operator&=(const SIMD_SSE2& other)
{
reg = _mm_and_si128(reg, other.reg);
diff --git a/src/wrap/sqlite/codec.cpp b/src/wrap/sqlite/codec.cpp
new file mode 100644
index 000000000..5dfcea82e
--- /dev/null
+++ b/src/wrap/sqlite/codec.cpp
@@ -0,0 +1,123 @@
+/*
+ * Codec class for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#include "codec.h"
+#include <botan/init.h>
+
+Codec::Codec(void *db)
+{
+ InitializeCodec(db);
+}
+
+Codec::Codec(const Codec& other, void *db)
+{
+ //Only used to copy main db key for an attached db
+ InitializeCodec(db);
+ m_hasReadKey = other.m_hasReadKey;
+ m_hasWriteKey = other.m_hasWriteKey;
+ m_readKey = other.m_readKey;
+ m_ivReadKey = other.m_ivReadKey;
+ m_writeKey = other.m_writeKey;
+ m_ivWriteKey = other.m_ivWriteKey;
+}
+
+void
+Codec::InitializeCodec(void *db)
+{
+ bool botanInitialized = false;
+ Library_State* state = swap_global_state(0);
+ if(state)
+ {
+ botanInitialized = true;
+ swap_global_state(state); // should return NULL FIXME: what if not?
+ }
+
+ if (!botanInitialized)
+ LibraryInitializer::initialize();
+
+ m_hasReadKey = false;
+ m_hasWriteKey = false;
+ m_db = db;
+
+ m_encipherFilter = get_cipher(BLOCK_CIPHER_STR, ENCRYPTION);
+ m_decipherFilter = get_cipher(BLOCK_CIPHER_STR, DECRYPTION);
+ m_cmac = new MAC_Filter(MAC_STR);
+ m_encipherPipe.append(m_encipherFilter);
+ m_decipherPipe.append(m_decipherFilter);
+ m_macPipe.append(m_cmac);
+}
+
+void
+Codec::GenerateWriteKey(const char* userPassword, int passwordLength)
+{
+ S2K* s2k = get_s2k(S2K_STR);
+ s2k->set_iterations(S2K_ITERATIONS);
+ s2k->change_salt((const byte*)SALT_STR.c_str(), SALT_SIZE);
+
+ SymmetricKey masterKey =
+ s2k->derive_key(KEY_SIZE + IV_DERIVATION_KEY_SIZE, std::string(userPassword, passwordLength));
+
+ m_writeKey = SymmetricKey(masterKey.bits_of(), KEY_SIZE);
+ m_ivWriteKey = SymmetricKey(masterKey.bits_of() + KEY_SIZE, IV_DERIVATION_KEY_SIZE);
+
+ m_hasWriteKey = true;
+}
+
+void
+Codec::DropWriteKey()
+{
+ m_hasWriteKey = false;
+}
+
+void
+Codec::SetReadIsWrite()
+{
+ m_readKey = m_writeKey;
+ m_ivReadKey = m_ivWriteKey;
+ m_hasReadKey = m_hasWriteKey;
+}
+
+void
+Codec::SetWriteIsRead()
+{
+ m_writeKey = m_readKey;
+ m_ivWriteKey = m_ivReadKey;
+ m_hasWriteKey = m_hasReadKey;
+}
+
+unsigned char *
+Codec::Encrypt(int page, unsigned char* data, bool useWriteKey)
+{
+ memcpy(m_page, data, m_pageSize);
+
+ m_encipherFilter->set_key(useWriteKey ? m_writeKey : m_readKey);
+ m_encipherFilter->set_iv(GetIVForPage(page, useWriteKey));
+ m_encipherPipe.process_msg(m_page, m_pageSize);
+ m_encipherPipe.read(m_page, m_encipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
+
+ return m_page; //return location of newly ciphered data
+}
+
+void
+Codec::Decrypt(int page, unsigned char* data)
+{
+ m_decipherFilter->set_key(m_readKey);
+ m_decipherFilter->set_iv(GetIVForPage(page, false));
+ m_decipherPipe.process_msg(data, m_pageSize);
+ m_decipherPipe.read(data, m_decipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
+}
+
+InitializationVector
+Codec::GetIVForPage(u32bit page, bool useWriteKey)
+{
+ static unsigned char* intiv[4];
+ store_le(page, (byte*)intiv);
+ m_cmac->set_key(useWriteKey ? m_ivWriteKey : m_ivReadKey);
+ m_macPipe.process_msg((byte*)intiv, 4);
+ return m_macPipe.read_all(Pipe::LAST_MESSAGE);
+}
+
diff --git a/src/wrap/sqlite/codec.h b/src/wrap/sqlite/codec.h
new file mode 100644
index 000000000..8b753be62
--- /dev/null
+++ b/src/wrap/sqlite/codec.h
@@ -0,0 +1,127 @@
+/*
+ * Codec class for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#ifndef _CODEC_H_
+#define _CODEC_H_
+
+#include <string>
+#include <botan/botan.h>
+#include <botan/loadstor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__BORLANDC__)
+#define __STDC__ 1
+#endif
+
+#include "./sqliteInt.h"
+
+#if defined(__BORLANDC__)
+#undef __STDC__
+#endif
+
+/* ATTENTION: Macro similar to that in pager.c
+ * Needed because pager is forward declared when needed most
+ * TODO: Check in case of new version of SQLite
+ * ... but it's VERY unlikely to change (it'd break all past DBs)
+ */
+#include "./os.h"
+#define CODEC_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
+
+#ifdef __cplusplus
+} /* End of the 'extern "C"' block */
+#endif
+
+using namespace std;
+using namespace Botan;
+
+/*These constants can be used to tweak the codec behavior as follows
+ *Note that once you've encrypted a database with these settings,
+ *recompiling with any different settings will give you a library that
+ *cannot read that database, even given the same passphrase.*/
+
+//BLOCK_CIPHER_STR: Cipher and mode used for encrypting the database
+//make sure to add "/NoPadding" for modes that use padding schemes
+const string BLOCK_CIPHER_STR = "Twofish/XTS";
+
+//S2K_STR: Key derivation function used to derive both the encryption
+//and IV derivation keys from the given database passphrase
+const string S2K_STR = "PBKDF2(SHA-160)";
+
+//SALT_STR: Hard coded salt used to derive the key from the passphrase.
+const string SALT_STR = "&g#nB'9]";
+
+//MAC_STR: CMAC used to derive the IV that is used for db page
+//encryption
+const string MAC_STR = "CMAC(Twofish)";
+
+//S2K_ITERATIONS: Number of hash iterations used in the key derivation
+//process.
+const int S2K_ITERATIONS = 10000;
+
+//SALT_SIZE: Size of the salt in bytes (as given in SALT_STR)
+const int SALT_SIZE = 64/8; //64 bit, 8 byte salt
+
+//KEY_SIZE: Size of the encryption key. Note that XTS splits the key
+//between two ciphers, so if you're using XTS, double the intended key
+//size. (ie, "AES-128/XTS" should have a 256 bit KEY_SIZE)
+const int KEY_SIZE = 512/8; //512 bit, 64 byte key. (256 bit XTS key)
+
+//IV_DERIVATION_KEY_SIZE: Size of the key used with the CMAC (MAC_STR)
+//above.
+const int IV_DERIVATION_KEY_SIZE = 256/8; //256 bit, 32 byte key
+
+class Codec
+{
+public:
+ Codec(void *db);
+ Codec(const Codec& other, void *db);
+
+ void GenerateWriteKey(const char* userPassword, int passwordLength);
+ void DropWriteKey();
+ void SetWriteIsRead();
+ void SetReadIsWrite();
+
+ unsigned char* Encrypt(int page, unsigned char* data, bool useWriteKey);
+ void Decrypt(int page, unsigned char* data);
+
+ void SetPageSize(int pageSize) { m_pageSize = pageSize; }
+
+ bool HasReadKey() { return m_hasReadKey; }
+ bool HasWriteKey() { return m_hasWriteKey; }
+ void* GetDB() { return m_db; }
+
+private:
+ bool m_hasReadKey;
+ bool m_hasWriteKey;
+
+ SymmetricKey
+ m_readKey,
+ m_writeKey,
+ m_ivReadKey,
+ m_ivWriteKey;
+
+ Pipe
+ m_encipherPipe,
+ m_decipherPipe,
+ m_macPipe;
+
+ Keyed_Filter *m_encipherFilter;
+ Keyed_Filter *m_decipherFilter;
+ MAC_Filter *m_cmac;
+
+ int m_pageSize;
+ unsigned char m_page[SQLITE_MAX_PAGE_SIZE];
+ void* m_db;
+
+ InitializationVector GetIVForPage(u32bit page, bool useWriteKey);
+ void InitializeCodec(void *db);
+};
+
+#endif
diff --git a/src/wrap/sqlite/codecext.cpp b/src/wrap/sqlite/codecext.cpp
new file mode 100644
index 000000000..e542df975
--- /dev/null
+++ b/src/wrap/sqlite/codecext.cpp
@@ -0,0 +1,261 @@
+/*
+ * SQLite3 encryption extention codec
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#ifndef SQLITE_OMIT_DISKIO
+#ifdef SQLITE_HAS_CODEC
+
+#include "codec.h"
+#include "sqlite3.h"
+
+// Required to implement, called from pragma.c, guessing that "see" is related to the
+// "SQLite Encryption Extension" (the semi-official, for-pay, encryption codec)
+extern "C"
+void sqlite3_activate_see(const char *info) { }
+
+// Free the encryption codec, called from pager.c (address passed in sqlite3PagerSetCodec)
+extern "C"
+void sqlite3PagerFreeCodec(void *pCodec)
+{
+ if (pCodec)
+ delete (Codec*) pCodec;
+}
+
+// Report the page size to the codec, called from pager.c (address passed in sqlite3PagerSetCodec)
+extern "C"
+void sqlite3CodecSizeChange(void *pCodec, int pageSize, int nReserve)
+{
+ Codec* codec = (Codec*) pCodec;
+ codec->SetPageSize(pageSize);
+}
+
+// Encrypt/Decrypt functionality, called by pager.c
+extern "C"
+void* sqlite3Codec(void* pCodec, void* data, Pgno nPageNum, int nMode)
+{
+ if (pCodec == NULL) //Db not encrypted
+ return data;
+
+ Codec* codec = (Codec*) pCodec;
+
+ try
+ {
+ switch(nMode)
+ {
+ case 0: // Undo a "case 7" journal file encryption
+ case 2: // Reload a page
+ case 3: // Load a page
+ if (codec->HasReadKey())
+ codec->Decrypt(nPageNum, (unsigned char*) data);
+ break;
+ case 6: // Encrypt a page for the main database file
+ if (codec->HasWriteKey())
+ data = codec->Encrypt(nPageNum, (unsigned char*) data, true);
+ break;
+ case 7: // Encrypt a page for the journal file
+ /*
+ *Under normal circumstances, the readkey is the same as the writekey. However,
+ *when the database is being rekeyed, the readkey is not the same as the writekey.
+ *(The writekey is the "destination key" for the rekey operation and the readkey
+ *is the key the db is currently encrypted with)
+ *Therefore, for case 7, when the rollback is being written, always encrypt using
+ *the database's readkey, which is guaranteed to be the same key that was used to
+ *read and write the original data.
+ */
+ if (codec->HasReadKey())
+ data = codec->Encrypt(nPageNum, (unsigned char*) data, false);
+ break;
+ }
+ }
+ catch(Botan::Exception e)
+ {
+ sqlite3Error((sqlite3*)codec->GetDB(), SQLITE_ERROR, "Botan Error: %s", e.what());
+ }
+
+ return data;
+}
+
+//These functions are defined in pager.c
+extern "C" void* sqlite3PagerGetCodec(Pager *pPager);
+extern "C" void sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+ void (*xCodecFree)(void*),
+ void *pCodec
+);
+
+
+extern "C"
+int sqlite3CodecAttach(sqlite3* db, int nDb, const void* zKey, int nKey)
+{
+ try {
+ if (zKey == NULL || nKey <= 0)
+ {
+ // No key specified, could mean either use the main db's encryption or no encryption
+ if (nDb != 0 && nKey < 0)
+ {
+ //Is an attached database, therefore use the key of main database, if main database is encrypted
+ Codec* mainCodec = (Codec*) sqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
+ if (mainCodec != NULL)
+ {
+ Codec* codec = new Codec(*mainCodec, db);
+ sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
+ sqlite3Codec,
+ sqlite3CodecSizeChange,
+ sqlite3PagerFreeCodec, codec);
+ }
+ }
+ }
+ else
+ {
+ // Key specified, setup encryption key for database
+ Codec* codec = new Codec(db);
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ codec->SetReadIsWrite();
+ sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
+ sqlite3Codec,
+ sqlite3CodecSizeChange,
+ sqlite3PagerFreeCodec, codec);
+ }
+ }
+ catch(Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error: %s", e.what());
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+extern "C"
+void sqlite3CodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey)
+{
+ // The unencrypted password is not stored for security reasons
+ // therefore always return NULL
+ *zKey = NULL;
+ *nKey = -1;
+}
+
+extern "C"
+int sqlite3_key(sqlite3 *db, const void *zKey, int nKey)
+{
+ // The key is only set for the main database, not the temp database
+ return sqlite3CodecAttach(db, 0, zKey, nKey);
+}
+
+extern "C"
+int sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey)
+{
+ // Changes the encryption key for an existing database.
+ int rc = SQLITE_ERROR;
+ Btree* pbt = db->aDb[0].pBt;
+ Pager* pPager = sqlite3BtreePager(pbt);
+ Codec* codec = (Codec*) sqlite3PagerGetCodec(pPager);
+
+ if ((zKey == NULL || nKey == 0) && codec == NULL)
+ {
+ // Database not encrypted and key not specified. Do nothing
+ return SQLITE_OK;
+ }
+
+ if (codec == NULL)
+ {
+ // Database not encrypted, but key specified. Encrypt database
+ try {
+ codec = new Codec(db);
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ } catch (Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error %s", e.what());
+ return SQLITE_ERROR;
+ }
+ sqlite3PagerSetCodec(pPager, sqlite3Codec, sqlite3CodecSizeChange, sqlite3PagerFreeCodec, codec);
+ }
+ else if (zKey == NULL || nKey == 0)
+ {
+ // Database encrypted, but key not specified. Decrypt database
+ // Keep read key, drop write key
+ codec->DropWriteKey();
+ }
+ else
+ {
+ // Database encrypted and key specified. Re-encrypt database with new key
+ // Keep read key, change write key to new key
+ try {
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ } catch (Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error %s", e.what());
+ return SQLITE_ERROR;
+ }
+ }
+
+ // Start transaction
+ rc = sqlite3BtreeBeginTrans(pbt, 1);
+ if (rc == SQLITE_OK)
+ {
+ // Rewrite all pages using the new encryption key (if specified)
+ int nPageCount = -1;
+ int rc = sqlite3PagerPagecount(pPager, &nPageCount);
+ Pgno nPage = (Pgno) nPageCount;
+ int pageSize = sqlite3BtreeGetPageSize(pbt);
+ //Can't use SQLite3 macro here since pager is forward declared...sigh
+ Pgno nSkip = CODEC_PAGER_MJ_PGNO(pageSize);
+ DbPage *pPage;
+
+ for (Pgno n = 1; rc == SQLITE_OK && n <= nPage; n++)
+ {
+ if (n == nSkip)
+ continue;
+
+ rc = sqlite3PagerGet(pPager, n, &pPage);
+
+ if (!rc)
+ {
+ rc = sqlite3PagerWrite(pPage);
+ sqlite3PagerUnref(pPage);
+ }
+ else
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Error while rekeying database page. Transaction Canceled.");
+ }
+ }
+ else
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Error beginning rekey transaction. Make sure that the current encryption key is correct.");
+
+ if (rc == SQLITE_OK)
+ {
+ // All good, commit
+ rc = sqlite3BtreeCommit(pbt);
+
+ if (rc == SQLITE_OK)
+ {
+ //Database rekeyed and committed successfully, update read key
+ if (codec->HasWriteKey())
+ codec->SetReadIsWrite();
+ else //No write key == no longer encrypted
+ sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ //FIXME: can't trigger this, not sure if rollback is needed, reference implementation didn't rollback
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Could not commit rekey transaction.");
+ }
+ }
+ else
+ {
+ // Rollback, rekey failed
+ sqlite3BtreeRollback(pbt);
+
+ // go back to read key
+ if (codec->HasReadKey())
+ codec->SetWriteIsRead();
+ else //Database wasn't encrypted to start with
+ sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
+ }
+
+ return rc;
+}
+
+#endif // SQLITE_HAS_CODEC
+
+#endif // SQLITE_OMIT_DISKIO
diff --git a/src/wrap/sqlite/readme.txt b/src/wrap/sqlite/readme.txt
new file mode 100644
index 000000000..e131f9e91
--- /dev/null
+++ b/src/wrap/sqlite/readme.txt
@@ -0,0 +1,36 @@
+Build instructions for Botan SQLite3 codec
+---
+
+1. Requires Botan 1.8.8 or later (earlier versions OK if you switch to
+ CBC mode from XTS)
+
+2. Download SQLite3 version 3.6.17 or later, get the version "as
+ extracted from the source control system", NOT the amalgamation.
+
+3. Apply the patch "sqlite.diff" [*]:
+ $ patch -p0 < ../sqlite.diff
+ patching file Makefile.in
+ patching file src/pager.c
+
+ If the patch to pager.c fails for some reason (ie, changes in
+ SQLite3), all that need be done is remove the "static" keyword from
+ the functions sqlite3PagerSetCodec and sqlite3PagerGetCodec.
+
+5. Create a folder called "botan" in the SQLite3 src dir and copy
+ "codec.cpp", "codec.h", and "codecext.cpp" into it.
+
+6. As desired, edit the constants in codec.h to tweak the encryption
+ type to your needs. (Currently, Twofish/XTS with 256 bit key)
+
+7. Run ./configure in the SQLite3 root directory with the
+ "--disable-amalgamation" and (if desired) "--disable-shared"
+ arguments, and then run make.
+
+And to make sure it all worked...
+
+8. Make the test_sqlite.cpp file:
+ $ g++ test_sqlite.cpp -o test_sqlite -lbotan /path/to/libsqlite3.a
+9. Run it
+ $ ./test_sqlite
+10. Look for "All seems good"
+
diff --git a/src/wrap/sqlite/sqlite.diff b/src/wrap/sqlite/sqlite.diff
new file mode 100644
index 000000000..1a3ef764c
--- /dev/null
+++ b/src/wrap/sqlite/sqlite.diff
@@ -0,0 +1,77 @@
+--- Makefile.in.orig 2009-10-30 09:34:59.000000000 -0400
++++ Makefile.in 2010-01-21 22:51:22.000000000 -0500
+@@ -133,7 +133,10 @@
+ GCOV_LDFLAGS1 = -lgcov
+ USE_GCOV = @USE_GCOV@
+ LTCOMPILE_EXTRAS += $(GCOV_CFLAGS$(USE_GCOV))
++LTCOMPILE_EXTRAS += -DSQLITE_HAS_CODEC
+ LTLINK_EXTRAS += $(GCOV_LDFLAGS$(USE_GCOV))
++LTLINK_EXTRAS += -lstdc++
++LTLINK_EXTRAS += -lbotan
+
+
+ # The directory into which to store package information for
+@@ -176,7 +179,8 @@
+ table.lo tokenize.lo trigger.lo update.lo \
+ util.lo vacuum.lo \
+ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo \
+- walker.lo where.lo utf.lo vtab.lo
++ walker.lo where.lo utf.lo vtab.lo \
++ codec.lo codecext.lo
+
+ # Object files for the amalgamation.
+ #
+@@ -275,7 +279,10 @@
+ $(TOP)/src/vdbeInt.h \
+ $(TOP)/src/vtab.c \
+ $(TOP)/src/walker.c \
+- $(TOP)/src/where.c
++ $(TOP)/src/where.c \
++ $(TOP)/src/botan/codec.cpp \
++ $(TOP)/src/botan/codecext.cpp \
++ $(TOP)/src/botan/codec.h
+
+ # Generated source code files
+ #
+@@ -411,6 +418,7 @@
+ $(TOP)/src/sqlite3ext.h \
+ $(TOP)/src/sqliteInt.h \
+ $(TOP)/src/vdbe.h \
++ $(TOP)/src/botan/codec.h \
+ $(TOP)/src/vdbeInt.h \
+ parse.h \
+ config.h
+@@ -622,6 +630,13 @@
+ notify.lo: $(TOP)/src/notify.c $(HDR)
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/notify.c
+
++codec.lo: $(TOP)/src/botan/codec.cpp $(HDR) $(TOP)/src/botan/codec.h
++ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/botan/codec.cpp
++
++codecext.lo: $(TOP)/src/botan/codecext.cpp $(HDR) $(TOP)/src/botan/codec.h
++ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/botan/codecext.cpp
++
++
+ pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pager.c
+
+--- src/pager.c.orig 2009-10-30 17:01:07.000000000 -0400
++++ src/pager.c 2010-01-21 22:51:53.000000000 -0500
+@@ -5046,7 +5046,7 @@
+ /*
+ ** Set or retrieve the codec for this pager
+ */
+-static void sqlite3PagerSetCodec(
++void sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+@@ -5060,7 +5060,7 @@
+ pPager->pCodec = pCodec;
+ pagerReportSize(pPager);
+ }
+-static void *sqlite3PagerGetCodec(Pager *pPager){
++void *sqlite3PagerGetCodec(Pager *pPager){
+ return pPager->pCodec;
+ }
+ #endif
diff --git a/src/wrap/sqlite/test_sqlite.cpp b/src/wrap/sqlite/test_sqlite.cpp
new file mode 100644
index 000000000..8d8cad946
--- /dev/null
+++ b/src/wrap/sqlite/test_sqlite.cpp
@@ -0,0 +1,101 @@
+/*
+ * Quick and dirty test for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#include <sqlite3.h>
+#include <stdio.h>
+
+namespace SQL
+{
+ const char * CREATE_TABLE_TEST =
+ "create table 'test' (id INTEGER PRIMARY KEY, name TEXT, creationtime TEXT);";
+ const char * CREATE_TABLE_TEST2 =
+ "create table 'test2' (id INTEGER PRIMARY KEY, name TEXT, creationtime TEXT);";
+ const char * INSERT_INTO_TEST =
+ "INSERT INTO test (name, creationtime) VALUES ('widget', '1st time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '2nd time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '3rd time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '4th time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '5th time');";
+ const char * INSERT_INTO_TEST2 =
+ "INSERT INTO test2 (name, creationtime) VALUES ('widget2', '1st time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '2nd time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '3rd time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '4th time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '5th time2');";
+ const char * SELECT_FROM_TEST =
+ "SELECT * FROM test;";
+ const char * SELECT_FROM_TEST2 =
+ "SELECT * FROM test2;";
+};
+
+static int callback(void *NotUsed, int argc, char **argv, char **azColName){
+ int i;
+ fprintf(stderr, "\t");
+ for(i=0; i<argc; i++){
+ fprintf(stderr, "%s = %s | ", azColName[i], argv[i] ? argv[i] : "NULL");
+ }
+ fprintf(stderr, "\n");
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ sqlite3 * db;
+ const char * key = "testkey";
+ const char * dbname = "./testdb";
+ int keylen = 7;
+ char * error=0;
+
+ fprintf(stderr, "Creating Database \"%s\"\n", dbname);
+ int rc = sqlite3_open(dbname, &db);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Keying Database with key \"%s\"\n", key);
+ rc = sqlite3_key(db, key, keylen);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Creating table \"test\"\n");
+ rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Creating table \"test2\"\n");
+ rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST2, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Inserting into table \"test\"\n");
+ rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Inserting into table \"test2\"\n");
+ rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST2, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Closing Database \"%s\"\n", dbname);
+ sqlite3_close(db);
+
+ fprintf(stderr, "Opening Database \"%s\"\n", dbname);
+ rc = sqlite3_open(dbname, &db);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Keying Database with key \"%s\"\n", key);
+ rc = sqlite3_key(db, key, keylen);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Selecting all from test\n");
+ rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST, callback, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Selecting all from test2\n");
+ rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST2, callback, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Closing Database \"%s\"\n", dbname);
+ sqlite3_close(db);
+
+ fprintf(stderr, "All Seems Good \n");
+ return 0;
+}