File encfs-new-iv-initialization.patch of Package encfs
---
encfs/SSL_Cipher.cpp | 60 +++++++++++++++++++++++++++++++++++----------------
encfs/SSL_Cipher.h | 6 ++++-
2 files changed, 47 insertions(+), 19 deletions(-)
Index: encfs-1.6.0/encfs/SSL_Cipher.h
===================================================================
--- encfs-1.6.0.orig/encfs/SSL_Cipher.h 2010-12-03 17:09:12.290131785 +0100
+++ encfs-1.6.0/encfs/SSL_Cipher.h 2010-12-03 17:10:43.482131783 +0100
@@ -137,8 +137,12 @@ class SSL_Cipher : public Cipher
// hack to help with static builds
static bool Enabled();
private:
- void setIVec( unsigned char *ivec, unsigned int seed,
+ void setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key ) const;
+
+ // deprecated - for backward compatibility
+ void setIVec_old( unsigned char *ivec, unsigned int seed,
+ const shared_ptr<SSLKey> &key ) const;
};
Index: encfs-1.6.0/encfs/SSL_Cipher.cpp
===================================================================
--- encfs-1.6.0.orig/encfs/SSL_Cipher.cpp 2009-11-29 23:04:12.000000000 +0100
+++ encfs-1.6.0/encfs/SSL_Cipher.cpp 2010-12-03 17:10:43.482131783 +0100
@@ -173,8 +173,9 @@ int TimedPBKDF2(const char *pass, int pa
// We support both 2:0 and 1:0, hence current:revision:age = 2:0:1
// - Version 2:1 adds support for Message Digest function interface
// - Version 2:2 adds PBKDF2 for password derivation
-static Interface BlowfishInterface( "ssl/blowfish", 2, 2, 1 );
-static Interface AESInterface( "ssl/aes", 2, 2, 1 );
+// - Version 3:0 adds a new IV mechanism
+static Interface BlowfishInterface( "ssl/blowfish", 3, 0, 2 );
+static Interface AESInterface( "ssl/aes", 3, 0, 2 );
#if defined(HAVE_EVP_BF)
@@ -399,13 +400,6 @@ CipherKey SSL_Cipher::newKey(const char
int &iterationCount, long desiredDuration,
const unsigned char *salt, int saltLen)
{
- const EVP_MD *md = EVP_sha1();
- if(!md)
- {
- rError("Unknown digest SHA1");
- return CipherKey();
- }
-
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
if(iterationCount == 0)
@@ -441,13 +435,6 @@ CipherKey SSL_Cipher::newKey(const char
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
{
- const EVP_MD *md = EVP_sha1();
- if(!md)
- {
- rError("Unknown digest SHA1");
- return CipherKey();
- }
-
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
int bytes = 0;
@@ -545,7 +532,7 @@ static uint64_t _checksum_64( SSLKey *ke
HMAC_Final( &key->mac_ctx, md, &mdLen );
- rAssert(mdLen != 0);
+ rAssert(mdLen >= 8);
// chop this down to a 64bit value..
unsigned char h[8] = {0,0,0,0,0,0,0,0};
@@ -690,9 +677,46 @@ int SSL_Cipher::cipherBlockSize() const
return EVP_CIPHER_block_size( _blockCipher );
}
-void SSL_Cipher::setIVec( unsigned char *ivec, unsigned int seed,
+void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const
{
+ if (iface.current() >= 3)
+ {
+ memcpy( ivec, IVData(key), _ivLength );
+
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int mdLen = EVP_MAX_MD_SIZE;
+
+ for(int i=0; i<8; ++i)
+ {
+ md[i] = (unsigned char)(seed & 0xff);
+ seed >>= 8;
+ }
+
+ // combine ivec and seed with HMAC
+ HMAC_Init_ex( &key->mac_ctx, 0, 0, 0, 0 );
+ HMAC_Update( &key->mac_ctx, ivec, _ivLength );
+ HMAC_Update( &key->mac_ctx, md, 8 );
+ HMAC_Final( &key->mac_ctx, md, &mdLen );
+ rAssert(mdLen >= _ivLength);
+
+ memcpy( ivec, md, _ivLength );
+ } else
+ {
+ setIVec_old(ivec, seed, key);
+ }
+}
+
+/** For backward compatibility.
+ A watermark attack was discovered against this IV setup. If an attacker
+ could get a victim to store a carefully crafted file, they could later
+ determine if the victim had the file in encrypted storage (without
+ decrypting the file).
+ */
+void SSL_Cipher::setIVec_old(unsigned char *ivec,
+ unsigned int seed,
+ const shared_ptr<SSLKey> &key) const
+{
/* These multiplication constants chosen as they represent (non optimal)
Golumb rulers, the idea being to spread around the information in the
seed.