aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/block/aes/aes.cpp4
-rw-r--r--src/block/blowfish/blowfish.cpp57
-rw-r--r--src/block/blowfish/blowfish.h19
-rw-r--r--src/block/mars/mars.cpp10
-rw-r--r--src/build-data/cc/sunstudio.txt4
-rw-r--r--src/cert/certstore/info.txt3
-rw-r--r--src/cert/x509cert/info.txt1
-rw-r--r--src/cert/x509cert/x509cert.cpp16
-rw-r--r--src/codec/pem/info.txt2
-rw-r--r--src/constructs/aont/package.cpp8
-rw-r--r--src/constructs/rfc3394/info.txt1
-rw-r--r--src/constructs/rfc3394/rfc3394.cpp122
-rw-r--r--src/constructs/rfc3394/rfc3394.h45
-rw-r--r--src/entropy/hres_timer/hres_timer.cpp2
-rw-r--r--src/filters/bzip2/bzip2.cpp24
-rw-r--r--src/filters/out_buf.cpp19
-rw-r--r--src/filters/zlib/zlib.cpp16
-rw-r--r--src/libstate/info.txt5
-rw-r--r--src/passhash/bcrypt/bcrypt.cpp154
-rw-r--r--src/passhash/bcrypt/bcrypt.h37
-rw-r--r--src/passhash/bcrypt/info.txt9
-rw-r--r--src/passhash/passhash9/info.txt (renamed from src/constructs/passhash/info.txt)0
-rw-r--r--src/passhash/passhash9/passhash9.cpp (renamed from src/constructs/passhash/passhash9.cpp)0
-rw-r--r--src/passhash/passhash9/passhash9.h (renamed from src/constructs/passhash/passhash9.h)0
-rw-r--r--src/ssl/info.txt2
-rw-r--r--src/stream/ctr/ctr.cpp4
26 files changed, 508 insertions, 56 deletions
diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp
index 7f32d243c..9fb12cd11 100644
--- a/src/block/aes/aes.cpp
+++ b/src/block/aes/aes.cpp
@@ -457,7 +457,7 @@ void aes_encrypt_n(const byte in[], byte out[],
rotate_right(TE[get_byte(2, T1)], 16) ^
rotate_right(TE[get_byte(3, T2)], 24) ^ EK[7];
- for(u32bit r = 2*4; r < EK.size(); r += 2*4)
+ for(size_t r = 2*4; r < EK.size(); r += 2*4)
{
T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^
TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ EK[r];
@@ -560,7 +560,7 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
rotate_right(TD[get_byte(2, T1)], 16) ^
rotate_right(TD[get_byte(3, T0)], 24) ^ DK[7];
- for(u32bit r = 2*4; r < DK.size(); r += 2*4)
+ for(size_t r = 2*4; r < DK.size(); r += 2*4)
{
T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^
TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ DK[r];
diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp
index ea227e93e..b6319eec0 100644
--- a/src/block/blowfish/blowfish.cpp
+++ b/src/block/blowfish/blowfish.cpp
@@ -1,6 +1,6 @@
/*
* Blowfish
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -87,20 +87,66 @@ void Blowfish::key_schedule(const byte key[], size_t length)
{
clear();
+ const byte null_salt[16] = { 0 };
+
+ key_expansion(key, length, null_salt);
+ }
+
+void Blowfish::key_expansion(const byte key[],
+ size_t length,
+ const byte salt[16])
+ {
for(size_t i = 0, j = 0; i != 18; ++i, j += 4)
P[i] ^= make_u32bit(key[(j ) % length], key[(j+1) % length],
key[(j+2) % length], key[(j+3) % length]);
u32bit L = 0, R = 0;
- generate_sbox(P, L, R);
- generate_sbox(S, L, R);
+ generate_sbox(P, L, R, salt, 0);
+ generate_sbox(S, L, R, salt, 2);
+ }
+
+/*
+* Modified key schedule used for bcrypt password hashing
+*/
+void Blowfish::eks_key_schedule(const byte key[], size_t length,
+ const byte salt[16], size_t workfactor)
+ {
+ if(length == 0 || length >= 56)
+ throw Invalid_Key_Length("EKSBlowfish", length);
+
+ if(workfactor == 0)
+ throw std::invalid_argument("Bcrypt work factor must be at least 1");
+
+ /*
+ * On a 2.8 GHz Core-i7, workfactor == 18 takes about 25 seconds to
+ * hash a password. This seems like a reasonable upper bound for the
+ * time being.
+ */
+ if(workfactor > 18)
+ throw std::invalid_argument("Requested Bcrypt work factor too large");
+
+ clear();
+
+ const byte null_salt[16] = { 0 };
+
+ key_expansion(key, length, salt);
+
+ const size_t rounds = 1 << workfactor;
+
+ for(size_t r = 0; r != rounds; ++r)
+ {
+ key_expansion(key, length, null_salt);
+ key_expansion(salt, 16, null_salt);
+ }
}
/*
* Generate one of the Sboxes
*/
void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
- u32bit& L, u32bit& R) const
+ u32bit& L, u32bit& R,
+ const byte salt[16],
+ size_t salt_off) const
{
const u32bit* S1 = &S[0];
const u32bit* S2 = &S[256];
@@ -109,6 +155,9 @@ void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
for(size_t i = 0; i != box.size(); i += 2)
{
+ L ^= load_be<u32bit>(salt, (i + salt_off) % 4);
+ R ^= load_be<u32bit>(salt, (i + salt_off + 1) % 4);
+
for(size_t j = 0; j != 16; j += 2)
{
L ^= P[j];
diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h
index b89ffcaaa..13706d21e 100644
--- a/src/block/blowfish/blowfish.h
+++ b/src/block/blowfish/blowfish.h
@@ -1,6 +1,6 @@
/*
* Blowfish
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -21,15 +21,28 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
+ /**
+ * Modified EKSBlowfish key schedule, used for bcrypt password hashing
+ */
+ void eks_key_schedule(const byte key[], size_t key_length,
+ const byte salt[16], size_t workfactor);
+
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[], size_t);
+ void key_schedule(const byte key[], size_t length);
+
+ void key_expansion(const byte key[],
+ size_t key_length,
+ const byte salt[16]);
+
void generate_sbox(MemoryRegion<u32bit>& box,
- u32bit& L, u32bit& R) const;
+ u32bit& L, u32bit& R,
+ const byte salt[16],
+ size_t salt_off) const;
static const u32bit P_INIT[18];
static const u32bit S_INIT[1024];
diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp
index 5ee5b0f19..171ce2945 100644
--- a/src/block/mars/mars.cpp
+++ b/src/block/mars/mars.cpp
@@ -110,7 +110,7 @@ const u32bit SBOX[512] = {
inline void encrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D,
u32bit EK1, u32bit EK2)
{
- u32bit X = A + EK1;
+ const u32bit X = A + EK1;
A = rotate_left(A, 13);
u32bit Y = A * EK2;
u32bit Z = SBOX[X % 512];
@@ -132,7 +132,7 @@ inline void decrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D,
{
u32bit Y = A * EK1;
A = rotate_right(A, 13);
- u32bit X = A + EK2;
+ const u32bit X = A + EK2;
u32bit Z = SBOX[X % 512];
Y = rotate_left(Y, 5);
@@ -204,7 +204,7 @@ u32bit gen_mask(u32bit input)
for(u32bit j = 2; j != 31; ++j)
{
- u32bit region = (input >> (j-1)) & 0x07;
+ const u32bit region = (input >> (j-1)) & 0x07;
if(region == 0x00 || region == 0x07)
{
@@ -213,7 +213,7 @@ u32bit gen_mask(u32bit input)
for(u32bit k = low; k != high; ++k)
{
- u32bit value = (input >> k) & 0x3FF;
+ const u32bit value = (input >> k) & 0x3FF;
if(value == 0 || value == 0x3FF)
{
@@ -377,7 +377,7 @@ void MARS::key_schedule(const byte key[], size_t length)
for(size_t i = 5; i != 37; i += 2)
{
- u32bit key3 = EK[i] & 3;
+ const u32bit key3 = EK[i] & 3;
EK[i] |= 3;
EK[i] ^= rotate_left(SBOX[265 + key3], EK[i-1] % 32) & gen_mask(EK[i]);
}
diff --git a/src/build-data/cc/sunstudio.txt b/src/build-data/cc/sunstudio.txt
index 91a6ace65..d0b25d144 100644
--- a/src/build-data/cc/sunstudio.txt
+++ b/src/build-data/cc/sunstudio.txt
@@ -45,7 +45,9 @@ sparc64 -> "-xchip=SUBMODEL" sparc64-
</mach_opt>
<mach_abi_linking>
-# On Linux, may need -library=stlport4
+# Needed on some Linux distros
+#linux -> "-library=stlport4"
+
sparc64 -> "-xarch=v9"
amd64 -> "-m64"
</mach_abi_linking>
diff --git a/src/cert/certstore/info.txt b/src/cert/certstore/info.txt
index ee730490f..a5de1baff 100644
--- a/src/cert/certstore/info.txt
+++ b/src/cert/certstore/info.txt
@@ -1,5 +1,6 @@
define CERTIFICATE_STORE
<requires>
-asn1
+x509cert
+x509crl
</requires>
diff --git a/src/cert/x509cert/info.txt b/src/cert/x509cert/info.txt
index 3be50f077..5e3715e7a 100644
--- a/src/cert/x509cert/info.txt
+++ b/src/cert/x509cert/info.txt
@@ -2,4 +2,5 @@ define X509_CERTIFICATES
<requires>
certstore
+datastor
</requires>
diff --git a/src/cert/x509cert/x509cert.cpp b/src/cert/x509cert/x509cert.cpp
index a431cb66d..40b61b47d 100644
--- a/src/cert/x509cert/x509cert.cpp
+++ b/src/cert/x509cert/x509cert.cpp
@@ -325,8 +325,8 @@ std::string X509_Certificate::to_string() const
continue;
out << "Subject " << dn_fields[i] << ":";
- for(size_t i = 0; i != vals.size(); ++i)
- out << " " << vals[i];
+ for(size_t j = 0; j != vals.size(); ++j)
+ out << " " << vals[j];
out << "\n";
}
@@ -338,8 +338,8 @@ std::string X509_Certificate::to_string() const
continue;
out << "Issuer " << dn_fields[i] << ":";
- for(size_t i = 0; i != vals.size(); ++i)
- out << " " << vals[i];
+ for(size_t j = 0; j != vals.size(); ++j)
+ out << " " << vals[j];
out << "\n";
}
@@ -374,16 +374,16 @@ std::string X509_Certificate::to_string() const
if(policies.size())
{
out << "Policies: " << "\n";
- for(u32bit j = 0; j != policies.size(); j++)
- out << " " << policies[j] << "\n";
+ for(size_t i = 0; i != policies.size(); i++)
+ out << " " << policies[i] << "\n";
}
std::vector<std::string> ex_constraints = this->ex_constraints();
if(ex_constraints.size())
{
out << "Extended Constraints:\n";
- for(u32bit j = 0; j != ex_constraints.size(); j++)
- out << " " << ex_constraints[j] << "\n";
+ for(size_t i = 0; i != ex_constraints.size(); i++)
+ out << " " << ex_constraints[i] << "\n";
}
out << "Signature algorithm: " <<
diff --git a/src/codec/pem/info.txt b/src/codec/pem/info.txt
index 88f36594c..6f9635d10 100644
--- a/src/codec/pem/info.txt
+++ b/src/codec/pem/info.txt
@@ -2,5 +2,5 @@ define PEM_CODEC
<requires>
base64
-filters
+codec_filt
</requires>
diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp
index 4d92a789c..4d46f6b61 100644
--- a/src/constructs/aont/package.cpp
+++ b/src/constructs/aont/package.cpp
@@ -46,13 +46,13 @@ void aont_package(RandomNumberGenerator& rng,
clear_mem(final_block, BLOCK_SIZE);
// XOR the hash blocks into the final block
- for(u32bit i = 0; i != blocks; ++i)
+ for(size_t i = 0; i != blocks; ++i)
{
const size_t left = std::min<size_t>(BLOCK_SIZE,
input_len - BLOCK_SIZE * i);
zeroise(buf);
- copy_mem(&buf[0], output + BLOCK_SIZE * i, left);
+ copy_mem(&buf[0], output + (BLOCK_SIZE * i), left);
for(size_t j = 0; j != sizeof(i); ++j)
buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
@@ -94,13 +94,13 @@ void aont_unpackage(BlockCipher* cipher,
const size_t blocks = ((input_len - 1) / BLOCK_SIZE);
// XOR the blocks into the package key bits
- for(u32bit i = 0; i != blocks; ++i)
+ for(size_t i = 0; i != blocks; ++i)
{
const size_t left = std::min<size_t>(BLOCK_SIZE,
input_len - BLOCK_SIZE * (i+1));
zeroise(buf);
- copy_mem(&buf[0], input + BLOCK_SIZE * i, left);
+ copy_mem(&buf[0], input + (BLOCK_SIZE * i), left);
for(size_t j = 0; j != sizeof(i); ++j)
buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
diff --git a/src/constructs/rfc3394/info.txt b/src/constructs/rfc3394/info.txt
new file mode 100644
index 000000000..496f3e138
--- /dev/null
+++ b/src/constructs/rfc3394/info.txt
@@ -0,0 +1 @@
+define RFC3394_KEYWRAP
diff --git a/src/constructs/rfc3394/rfc3394.cpp b/src/constructs/rfc3394/rfc3394.cpp
new file mode 100644
index 000000000..b000873fd
--- /dev/null
+++ b/src/constructs/rfc3394/rfc3394.cpp
@@ -0,0 +1,122 @@
+/*
+* AES Key Wrap (RFC 3394)
+* (C) 2011 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rfc3394.h>
+#include <botan/algo_factory.h>
+#include <botan/block_cipher.h>
+#include <botan/loadstor.h>
+#include <botan/exceptn.h>
+#include <botan/internal/xor_buf.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+BlockCipher* make_aes(size_t keylength,
+ Algorithm_Factory& af)
+ {
+ if(keylength == 16)
+ return af.make_block_cipher("AES-128");
+ else if(keylength == 24)
+ return af.make_block_cipher("AES-192");
+ else if(keylength == 32)
+ return af.make_block_cipher("AES-256");
+ else
+ throw std::invalid_argument("Bad KEK length for NIST keywrap");
+ }
+
+}
+
+SecureVector<byte> rfc3394_keywrap(const MemoryRegion<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));
+ aes->set_key(kek);
+
+ const size_t n = key.size() / 8;
+
+ SecureVector<byte> R((n + 1) * 8);
+ SecureVector<byte> A(16);
+
+ for(size_t i = 0; i != 8; ++i)
+ A[i] = 0xA6;
+
+ copy_mem(&R[8], key.begin(), key.size());
+
+ for(size_t j = 0; j <= 5; ++j)
+ {
+ for(size_t i = 1; i <= n; ++i)
+ {
+ const u32bit t = (n * j) + i;
+
+ copy_mem(&A[8], &R[8*i], 8);
+
+ aes->encrypt(&A[0]);
+ copy_mem(&R[8*i], &A[8], 8);
+
+ byte t_buf[4] = { 0 };
+ store_be(t, t_buf);
+ xor_buf(&A[4], &t_buf[0], 4);
+ }
+ }
+
+ copy_mem(&R[0], &A[0], 8);
+
+ return R;
+ }
+
+SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<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));
+ aes->set_key(kek);
+
+ const size_t n = (key.size() - 8) / 8;
+
+ SecureVector<byte> R(n * 8);
+ SecureVector<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);
+
+ for(size_t j = 0; j <= 5; ++j)
+ {
+ for(size_t i = n; i != 0; --i)
+ {
+ const u32bit t = (5 - j) * n + i;
+
+ byte t_buf[4] = { 0 };
+ store_be(t, t_buf);
+
+ xor_buf(&A[4], &t_buf[0], 4);
+
+ copy_mem(&A[8], &R[8*(i-1)], 8);
+
+ aes->decrypt(&A[0]);
+
+ copy_mem(&R[8*(i-1)], &A[8], 8);
+ }
+ }
+
+ if(load_be<u64bit>(&A[0], 0) != 0xA6A6A6A6A6A6A6A6)
+ throw Integrity_Failure("NIST key unwrap failed");
+
+ return R;
+ }
+
+}
diff --git a/src/constructs/rfc3394/rfc3394.h b/src/constructs/rfc3394/rfc3394.h
new file mode 100644
index 000000000..645586ee2
--- /dev/null
+++ b/src/constructs/rfc3394/rfc3394.h
@@ -0,0 +1,45 @@
+/*
+* AES Key Wrap (RFC 3394)
+* (C) 2011 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AES_KEY_WRAP_H__
+#define BOTAN_AES_KEY_WRAP_H__
+
+#include <botan/symkey.h>
+
+namespace Botan {
+
+class Algorithm_Factory;
+
+/**
+* Encrypt a key under a key encryption key using the algorithm
+* described in RFC 3394
+*
+* @param key the plaintext key to encrypt
+* @param kek the key encryption key
+* @param af an algorithm factory
+* @return key encrypted under kek
+*/
+SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key,
+ const SymmetricKey& kek,
+ Algorithm_Factory& af);
+
+/**
+* Decrypt a key under a key encryption key using the algorithm
+* described in RFC 3394
+*
+* @param key the encrypted key to decrypt
+* @param kek the key encryption key
+* @param af an algorithm factory
+* @return key decrypted under kek
+*/
+SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key,
+ const SymmetricKey& kek,
+ Algorithm_Factory& af);
+
+}
+
+#endif
diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp
index e9307743f..b0f99170a 100644
--- a/src/entropy/hres_timer/hres_timer.cpp
+++ b/src/entropy/hres_timer/hres_timer.cpp
@@ -45,7 +45,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
asm volatile("rpcc %0" : "=r" (rtc));
-#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64)
+#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
asm volatile("rd %%tick, %0" : "=r" (rtc));
#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
diff --git a/src/filters/bzip2/bzip2.cpp b/src/filters/bzip2/bzip2.cpp
index b166017c3..a291c1173 100644
--- a/src/filters/bzip2/bzip2.cpp
+++ b/src/filters/bzip2/bzip2.cpp
@@ -168,10 +168,14 @@ void Bzip_Compression::flush()
*/
void Bzip_Compression::clear()
{
- if(!bz) return;
- BZ2_bzCompressEnd(&(bz->stream));
- delete bz;
- bz = 0;
+ zeroise(buffer);
+
+ if(bz)
+ {
+ BZ2_bzCompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
}
/*
@@ -278,10 +282,14 @@ void Bzip_Decompression::end_msg()
*/
void Bzip_Decompression::clear()
{
- if(!bz) return;
- BZ2_bzDecompressEnd(&(bz->stream));
- delete bz;
- bz = 0;
+ zeroise(buffer);
+
+ if(bz)
+ {
+ BZ2_bzDecompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
}
}
diff --git a/src/filters/out_buf.cpp b/src/filters/out_buf.cpp
index 7fa13b8e3..7b79b4b70 100644
--- a/src/filters/out_buf.cpp
+++ b/src/filters/out_buf.cpp
@@ -1,6 +1,6 @@
/*
* Pipe Output Buffer
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -65,16 +65,17 @@ void Output_Buffers::add(SecureQueue* queue)
*/
void Output_Buffers::retire()
{
- while(buffers.size())
- {
- if(buffers[0] == 0 || buffers[0]->size() == 0)
+ for(size_t i = 0; i != buffers.size(); ++i)
+ if(buffers[i] && buffers[i]->size() == 0)
{
- delete buffers[0];
- buffers.pop_front();
- offset = offset + Pipe::message_id(1);
+ delete buffers[i];
+ buffers[i] = 0;
}
- else
- break;
+
+ while(buffers.size() && !buffers[0])
+ {
+ buffers.pop_front();
+ offset = offset + Pipe::message_id(1);
}
}
diff --git a/src/filters/zlib/zlib.cpp b/src/filters/zlib/zlib.cpp
index 30dee0225..0f88b5558 100644
--- a/src/filters/zlib/zlib.cpp
+++ b/src/filters/zlib/zlib.cpp
@@ -138,9 +138,11 @@ void Zlib_Compression::end_msg()
{
zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
zlib->stream.avail_out = buffer.size();
+
rc = deflate(&(zlib->stream), Z_FINISH);
send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
}
+
clear();
}
@@ -155,13 +157,13 @@ void Zlib_Compression::flush()
while(true)
{
zlib->stream.avail_out = buffer.size();
-
zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
-
deflate(&(zlib->stream), Z_FULL_FLUSH);
send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
- if(zlib->stream.avail_out == buffer.size()) break;
+
+ if(zlib->stream.avail_out == buffer.size())
+ break;
}
}
@@ -170,14 +172,14 @@ void Zlib_Compression::flush()
*/
void Zlib_Compression::clear()
{
+ zeroise(buffer);
+
if(zlib)
{
deflateEnd(&(zlib->stream));
delete zlib;
zlib = 0;
}
-
- buffer.clear();
}
/*
@@ -283,6 +285,8 @@ void Zlib_Decompression::end_msg()
*/
void Zlib_Decompression::clear()
{
+ zeroise(buffer);
+
no_writes = true;
if(zlib)
@@ -291,8 +295,6 @@ void Zlib_Decompression::clear()
delete zlib;
zlib = 0;
}
-
- buffer.clear();
}
}
diff --git a/src/libstate/info.txt b/src/libstate/info.txt
index a017589fc..ef0c9a47e 100644
--- a/src/libstate/info.txt
+++ b/src/libstate/info.txt
@@ -24,6 +24,7 @@ scan_name.cpp
</source>
<requires>
+aes
algo_factory
alloc
bigint
@@ -32,6 +33,8 @@ core_engine
engine
filters
hash
+hmac
+hmac_rng
kdf
mac
mode_pad
@@ -39,6 +42,8 @@ pbkdf
pk_pad
pubkey
rng
+sha2_32
+sha2_64
stream
system_alloc
</requires>
diff --git a/src/passhash/bcrypt/bcrypt.cpp b/src/passhash/bcrypt/bcrypt.cpp
new file mode 100644
index 000000000..e533c6081
--- /dev/null
+++ b/src/passhash/bcrypt/bcrypt.cpp
@@ -0,0 +1,154 @@
+/*
+* Bcrypt Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bcrypt.h>
+#include <botan/loadstor.h>
+#include <botan/libstate.h>
+#include <botan/blowfish.h>
+#include <botan/base64.h>
+
+#include <botan/pipe.h>
+#include <botan/b64_filt.h>
+#include <iostream>
+#include <stdio.h>
+
+namespace Botan {
+
+namespace {
+
+std::string bcrypt_base64_encode(const byte input[], size_t length)
+ {
+ // Bcrypt uses a non-standard base64 alphabet
+ const byte OPENBSD_BASE64_SUB[256] = {
+ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x38, 0x80, 0x80, 0x80, 0x39,
+ 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x2E, 0x2F, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
+ 0x76, 0x77, 0x78, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80
+ };
+
+ std::string b64 = base64_encode(input, length);
+
+ while(b64.size() && b64[b64.size()-1] == '=')
+ b64 = b64.substr(0, b64.size() - 1);
+
+ for(size_t i = 0; i != b64.size(); ++i)
+ b64[i] = OPENBSD_BASE64_SUB[static_cast<byte>(b64[i])];
+
+ return b64;
+ }
+
+MemoryVector<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,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x42,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
+ 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7A, 0x30, 0x31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80
+ };
+
+ for(size_t i = 0; i != input.size(); ++i)
+ input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])];
+
+ //return base64_decode(input);
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(input);
+ return pipe.read_all();
+ }
+
+std::string make_bcrypt(const std::string& pass,
+ const MemoryRegion<byte>& salt,
+ u16bit work_factor)
+ {
+ const byte magic[24] = {
+ 0x4F, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6E, 0x42,
+ 0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x53,
+ 0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74
+ };
+
+ MemoryVector<byte> ctext(magic, 24);
+
+ Blowfish blowfish;
+
+ // Include the trailing NULL byte
+ blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()),
+ pass.length() + 1,
+ salt,
+ work_factor);
+
+ for(size_t i = 0; i != 64; ++i)
+ blowfish.encrypt_n(&ctext[0], &ctext[0], 3);
+
+ 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 generate_bcrypt(const std::string& pass,
+ RandomNumberGenerator& rng,
+ u16bit work_factor)
+ {
+ return make_bcrypt(pass, rng.random_vec(16), work_factor);
+ }
+
+bool check_bcrypt(const std::string& pass, const std::string& hash)
+ {
+ if(hash.size() != 60 ||
+ hash[0] != '$' || hash[1] != '2' || hash[2] != 'a' ||
+ hash[3] != '$' || hash[6] != '$')
+ {
+ return false;
+ }
+
+ const u16bit workfactor = to_u32bit(hash.substr(4, 2));
+
+ MemoryVector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
+
+ const std::string compare = make_bcrypt(pass, salt, workfactor);
+
+ return (hash == compare);
+ }
+
+}
diff --git a/src/passhash/bcrypt/bcrypt.h b/src/passhash/bcrypt/bcrypt.h
new file mode 100644
index 000000000..8a6ab58ea
--- /dev/null
+++ b/src/passhash/bcrypt/bcrypt.h
@@ -0,0 +1,37 @@
+/*
+* Bcrypt Password Hashing
+* (C) 2011 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BCRYPT_H__
+#define BOTAN_BCRYPT_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Create a password hash using Bcrypt
+* @param password the password
+* @param rng a random number generator
+* @param work_factor how much work to do to slow down guessing attacks
+*
+* @see http://www.usenix.org/events/usenix99/provos/provos_html/
+*/
+std::string BOTAN_DLL generate_bcrypt(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_bcrypt(const std::string& password,
+ const std::string& hash);
+
+}
+
+#endif
diff --git a/src/passhash/bcrypt/info.txt b/src/passhash/bcrypt/info.txt
new file mode 100644
index 000000000..91ab92e88
--- /dev/null
+++ b/src/passhash/bcrypt/info.txt
@@ -0,0 +1,9 @@
+define BCRYPT
+
+<requires>
+libstate
+blowfish
+rng
+base64
+</requires>
+
diff --git a/src/constructs/passhash/info.txt b/src/passhash/passhash9/info.txt
index f96809f29..f96809f29 100644
--- a/src/constructs/passhash/info.txt
+++ b/src/passhash/passhash9/info.txt
diff --git a/src/constructs/passhash/passhash9.cpp b/src/passhash/passhash9/passhash9.cpp
index 367583a0a..367583a0a 100644
--- a/src/constructs/passhash/passhash9.cpp
+++ b/src/passhash/passhash9/passhash9.cpp
diff --git a/src/constructs/passhash/passhash9.h b/src/passhash/passhash9/passhash9.h
index 92cc391dc..92cc391dc 100644
--- a/src/constructs/passhash/passhash9.h
+++ b/src/passhash/passhash9/passhash9.h
diff --git a/src/ssl/info.txt b/src/ssl/info.txt
index 8f1eda497..1f11772cd 100644
--- a/src/ssl/info.txt
+++ b/src/ssl/info.txt
@@ -46,6 +46,8 @@ asn1
des
dh
dsa
+eme_pkcs
+emsa3
filters
hmac
md5
diff --git a/src/stream/ctr/ctr.cpp b/src/stream/ctr/ctr.cpp
index 0de0b7b84..d221dc441 100644
--- a/src/stream/ctr/ctr.cpp
+++ b/src/stream/ctr/ctr.cpp
@@ -97,7 +97,7 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len)
&counter[(i-1)*BLOCK_SIZE],
BLOCK_SIZE);
- for(u32bit j = 0; j != BLOCK_SIZE; ++j)
+ for(size_t j = 0; j != BLOCK_SIZE; ++j)
if(++counter[i*BLOCK_SIZE + (BLOCK_SIZE-1-j)])
break;
}
@@ -115,7 +115,7 @@ void CTR_BE::increment_counter()
for(size_t i = 0; i != 256; ++i)
{
- for(u32bit j = 1; j != BLOCK_SIZE; ++j)
+ for(size_t j = 1; j != BLOCK_SIZE; ++j)
if(++counter[i*BLOCK_SIZE + (BLOCK_SIZE-1-j)])
break;
}