Init
This commit is contained in:
45
DependentExtensions/cat/crypt/SecureCompare.hpp
Normal file
45
DependentExtensions/cat/crypt/SecureCompare.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SECURE_COMPARE_HPP
|
||||
#define CAT_SECURE_COMPARE_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Binary comparison function that is resistant to timing attack
|
||||
// Note that memcmp() and strcmp() are both vulnerable
|
||||
// Returns true if they are equal
|
||||
bool SecureEqual(const void *A, const void *B, int bytes);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // SECURE_COMPARE_HPP
|
||||
70
DependentExtensions/cat/crypt/cookie/CookieJar.hpp
Normal file
70
DependentExtensions/cat/crypt/cookie/CookieJar.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_COOKIE_JAR_HPP
|
||||
#define CAT_COOKIE_JAR_HPP
|
||||
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CookieJar
|
||||
{
|
||||
static const int EXPIRE_TIME = 4000; // ms
|
||||
static const int BIN_COUNT = 16; // power of 2
|
||||
static const int BIN_TIME = EXPIRE_TIME / BIN_COUNT;
|
||||
static const int BIN_MASK = BIN_COUNT - 1;
|
||||
|
||||
u32 key[16];
|
||||
|
||||
u32 Salsa6(u32 *x);
|
||||
|
||||
u32 Hash(u32 ip, u16 port, u32 epoch);
|
||||
u32 Hash(const void *address_info, int bytes, u32 epoch);
|
||||
|
||||
u32 GetEpoch();
|
||||
u32 ReconstructEpoch(u32 cookie);
|
||||
|
||||
public:
|
||||
// Initialize to a random 512-bit key on startup
|
||||
void Initialize(FortunaOutput *csprng);
|
||||
|
||||
// Thread-safe and lock-free
|
||||
u32 Generate(u32 ip, u16 port);
|
||||
u32 Generate(const void *address_info, int bytes); // bytes <= 48
|
||||
|
||||
// Thread-safe and lock-free
|
||||
bool Verify(u32 ip, u16 port, u32 cookie);
|
||||
bool Verify(const void *address_info, int bytes, u32 cookie); // bytes <= 48
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_COOKIE_JAR_HPP
|
||||
87
DependentExtensions/cat/crypt/hash/HMAC_MD5.hpp
Normal file
87
DependentExtensions/cat/crypt/hash/HMAC_MD5.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
HMAC-MD5 is still secure despite the ease of producing collisions in MD5.
|
||||
See Mihir Bellare paper "New Proofs for NMAC and HMAC: Security without Collision-Resistance" (June 2006)
|
||||
|
||||
Using HMAC construction:
|
||||
HMAC(x) = h(k || p1 || h(k || p2 || x))
|
||||
h() = MD5 hash
|
||||
p1,p2 = distinct padding to bring k up to the block size
|
||||
p1 = 0x36 repeated, p2 = 0x5c repeated
|
||||
|
||||
Diverges from usual implementation by using little-endian rather than big-endian input
|
||||
*/
|
||||
|
||||
#ifndef HMAC_MD5_HPP
|
||||
#define HMAC_MD5_HPP
|
||||
|
||||
#include <cat/crypt/hash/ICryptHash.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT HMAC_MD5 : public ICryptHash
|
||||
{
|
||||
protected:
|
||||
static const int DIGEST_BYTES = 16;
|
||||
static const int WORK_BYTES = 64; // bytes in one block
|
||||
static const int WORK_WORDS = WORK_BYTES / sizeof(u32);
|
||||
|
||||
u32 CachedInitialState[4]; // Cached state for H(K||inner padding)
|
||||
u32 CachedFinalState[4]; // Cached state for H(K||outer padding)
|
||||
|
||||
u64 byte_counter;
|
||||
u32 State[4];
|
||||
u8 Work[WORK_BYTES];
|
||||
int used_bytes;
|
||||
|
||||
void HashComputation(const void *message, int blocks, u32 *NextState);
|
||||
|
||||
// Unsupported modes
|
||||
bool BeginKey(int /*bits*/) { return false; }
|
||||
bool BeginKDF() { return false; }
|
||||
bool BeginPRNG() { return false; }
|
||||
|
||||
public:
|
||||
~HMAC_MD5();
|
||||
bool SetKey(ICryptHash *parent);
|
||||
void RekeyFromMD5(HMAC_MD5 *parent);
|
||||
bool BeginMAC();
|
||||
void Crunch(const void *message, int bytes);
|
||||
void End();
|
||||
|
||||
// TODO: Strengthening is not supported right now
|
||||
void Generate(void *out, int bytes, int strengthening_rounds = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // HMAC_MD5_HPP
|
||||
79
DependentExtensions/cat/crypt/hash/ICryptHash.hpp
Normal file
79
DependentExtensions/cat/crypt/hash/ICryptHash.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// 06/15/09 began
|
||||
|
||||
#ifndef CAT_I_CRYPT_HASH_HPP
|
||||
#define CAT_I_CRYPT_HASH_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Cryptographic hash functions of any size will derive from ICryptoHash and implement its public methods
|
||||
class CAT_EXPORT ICryptHash
|
||||
{
|
||||
protected:
|
||||
int digest_bytes;
|
||||
|
||||
public:
|
||||
virtual ~ICryptHash() {}
|
||||
|
||||
// Returns the number of bytes in a message digest produced by this hash
|
||||
CAT_INLINE int GetDigestByteCount() { return digest_bytes; }
|
||||
|
||||
CAT_INLINE void CrunchString(const char *s) { Crunch(s, (int)std::strlen(s) + 1); }
|
||||
|
||||
public:
|
||||
// Begin a new key
|
||||
virtual bool BeginKey(int bits) = 0;
|
||||
|
||||
// Start from an existing key
|
||||
virtual bool SetKey(ICryptHash *parent) = 0;
|
||||
|
||||
// Begin hash function in MAC, KDF, or PRNG mode
|
||||
virtual bool BeginMAC() = 0;
|
||||
virtual bool BeginKDF() = 0;
|
||||
virtual bool BeginPRNG() = 0;
|
||||
|
||||
// Crunch some message bytes
|
||||
virtual void Crunch(const void *message, int bytes) = 0;
|
||||
|
||||
// Finalize the hash and prepare to generate output
|
||||
virtual void End() = 0;
|
||||
|
||||
// Extended hash output mode
|
||||
virtual void Generate(void *out, int bytes, int strengthening_rounds = 0) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_I_CRYPT_HASH_HPP
|
||||
108
DependentExtensions/cat/crypt/hash/Skein.hpp
Normal file
108
DependentExtensions/cat/crypt/hash/Skein.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Bruce Schneier's SHA-3 candidate Skein hash function
|
||||
http://www.skein-hash.info/
|
||||
*/
|
||||
|
||||
#ifndef CAT_SKEIN_HPP
|
||||
#define CAT_SKEIN_HPP
|
||||
|
||||
#include <cat/crypt/hash/ICryptHash.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Base class for various versions of Skein
|
||||
class CAT_EXPORT Skein : public ICryptHash
|
||||
{
|
||||
protected:
|
||||
// Tweak word 1 bit field starting positions
|
||||
static const int T1_POS_TREE_LVL = 112-64; // bits 112..118 : level in hash tree
|
||||
static const int T1_POS_BIT_PAD = 119-64; // bit 119 : partial final input byte
|
||||
static const int T1_POS_BLK_TYPE = 120-64; // bits 120..125 : type field
|
||||
static const int T1_POS_FIRST = 126-64; // bits 126 : first block flag
|
||||
static const int T1_POS_FINAL = 127-64; // bit 127 : final block flag
|
||||
|
||||
// Tweak word 1 bit field masks
|
||||
static const u64 T1_MASK_FIRST = (u64)1 << T1_POS_FIRST;
|
||||
static const u64 T1_MASK_FINAL = (u64)1 << T1_POS_FINAL;
|
||||
static const u64 T1_MASK_BIT_PAD = (u64)1 << T1_POS_BIT_PAD;
|
||||
static const u64 T1_MASK_TREE_LVL = (u64)0x7F << T1_POS_TREE_LVL;
|
||||
static const u64 T1_MASK_BLK_TYPE = (u64)63 << T1_POS_BLK_TYPE;
|
||||
|
||||
static const int BLK_TYPE_KEY = 0; // key, for MAC and KDF
|
||||
static const int BLK_TYPE_CFG = 4; // configuration block
|
||||
static const int BLK_TYPE_PERS = 8; // personalization string
|
||||
static const int BLK_TYPE_PK = 12; // public key (for digital signature hashing)
|
||||
static const int BLK_TYPE_KDF = 16; // key identifier for KDF
|
||||
static const int BLK_TYPE_NONCE = 20; // nonce for PRNG
|
||||
static const int BLK_TYPE_MSG = 48; // message processing
|
||||
static const int BLK_TYPE_OUT = 63; // output stage
|
||||
|
||||
static const u32 ID_STRING_LE = 0x33414853;
|
||||
static const u32 SKEIN_VERSION = 1;
|
||||
static const u64 SCHEMA_VER = ((u64)SKEIN_VERSION << 32) | ID_STRING_LE;
|
||||
|
||||
static const int MAX_BITS = 512;
|
||||
static const int MAX_WORDS = MAX_BITS / 64;
|
||||
static const int MAX_BYTES = MAX_BITS / 8;
|
||||
|
||||
u64 Tweak[2];
|
||||
u64 State[MAX_WORDS];
|
||||
u8 Work[MAX_BYTES];
|
||||
int used_bytes, digest_words;
|
||||
u64 output_block_counter;
|
||||
bool output_prng_mode;
|
||||
|
||||
typedef void (Skein::*HashComputation)(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
|
||||
void HashComputation256(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
void HashComputation512(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
|
||||
HashComputation hash_func;
|
||||
|
||||
void GenerateInitialState(int bits);
|
||||
|
||||
public:
|
||||
~Skein();
|
||||
bool BeginKey(int bits);
|
||||
bool SetKey(ICryptHash *parent);
|
||||
bool BeginMAC();
|
||||
bool BeginKDF();
|
||||
bool BeginPRNG();
|
||||
void Crunch(const void *message, int bytes);
|
||||
void End();
|
||||
void Generate(void *out, int bytes, int strengthening_rounds = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SKEIN_HPP
|
||||
193
DependentExtensions/cat/crypt/pass/Passwords.hpp
Normal file
193
DependentExtensions/cat/crypt/pass/Passwords.hpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_PASSWORDS_HPP
|
||||
#define CAT_PASSWORDS_HPP
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Why are passwords needed?
|
||||
|
||||
Passwords allow the client identity to be proved to the server. Usually
|
||||
the server identity is already proven by a secure connection, but the
|
||||
client identity is unproven until a password is provided.
|
||||
|
||||
This could be done using signatures with two-way authentication in the
|
||||
secure connection establishment, however this is very slow and roughly
|
||||
doubles the work a server has to do to accept a connection.
|
||||
|
||||
Passwords seem simple to implement at first but then you start imagining all
|
||||
the "what ifs":
|
||||
|
||||
What if the password database is stolen?
|
||||
|
||||
The user passwords had better not be stored in plaintext!
|
||||
So they must be hashed.
|
||||
|
||||
What if two users have the same password?
|
||||
|
||||
They would look the same hashed, so hash in the name with the password.
|
||||
|
||||
What if name:password for two users is "me : pass" and "m : epass" ?
|
||||
|
||||
They would look the same hashed, so insert a separator between the two
|
||||
before hashing, as in "me\r\npass" instead of just hashing "mepass".
|
||||
|
||||
What if someone tries to crack the passwords?
|
||||
|
||||
The password hash should be strengthened to make it harder to crack,
|
||||
by applying the hash function repeatedly. This does reduce the number of
|
||||
bits of entropy due to non-ideal hash function collisions, but this small
|
||||
effect is offset by the added difficulty to crack the password.
|
||||
|
||||
What if the user has a common name like "dave"?
|
||||
|
||||
The password hash should be salted to avoid falling to rainbow tables.
|
||||
|
||||
What if the attacker tries to use the stolen password hash to log into the server?
|
||||
|
||||
The client provides a hash pre-image during login, so the attacker would need
|
||||
to reverse the hash to do this, which is harder than cracking the password.
|
||||
|
||||
What if an attacker has a way to actively or passively listen to login attempts?
|
||||
|
||||
Then they would be able to steal the hash pre-image which would offer some
|
||||
amount of text password protection but would allow the attacker to log in
|
||||
as the user without knowing the password.
|
||||
|
||||
Rainbow tables can be used to crack the pre-image to determine the password.
|
||||
|
||||
If the connection is secure then the client has verified the server identity
|
||||
and these attacks are only possible through software bugs in the server.
|
||||
|
||||
|
||||
Protocol Description:
|
||||
|
||||
H: 256-bit hash function Skein-256
|
||||
c: Client
|
||||
s: Server
|
||||
X: Strengthening factor
|
||||
|
||||
|
||||
Protocol 1: Creating a User Account
|
||||
|
||||
c: Choose a name N
|
||||
c: Choose a password P
|
||||
c: Calculate I = H("N\r\nP") strengthened X times
|
||||
|
||||
c2s CREATE_ACCOUNT || N || I (32 by)
|
||||
|
||||
s: Verify account is not taken, then creates an account in the database
|
||||
s: Generate a 32-bit random salt S
|
||||
s: Calculate J = H(S || I)
|
||||
s: Store N, J and S in the account
|
||||
|
||||
s2c ACCOUNT_CREATE_SUCCESS
|
||||
|
||||
|
||||
Protocol 2: Logging into a User Account
|
||||
|
||||
c: Choose a name N
|
||||
c: Choose a password P
|
||||
c: Calculate I = H("N\r\nP") strengthened X times
|
||||
|
||||
c2s LOGIN_REQUEST || N || I (32 by)
|
||||
|
||||
s: Verify user name exists in account database
|
||||
s: Retrieve J, S from the account database
|
||||
s: Calculate J' = H(S || I)
|
||||
s: Verify J = J'
|
||||
|
||||
s2c LOGIN_SUCCESS
|
||||
|
||||
|
||||
What if the user creates an account through a website?
|
||||
|
||||
The server-side script on the website should execute a program that runs
|
||||
Protocol 1 to create the user account.
|
||||
|
||||
Why use this sort of password authentication + Tunnel instead of SRP?
|
||||
|
||||
Performance. The Tunnel key agreement takes much less CPU time than SRP
|
||||
and authenticates the server, which allows this protocol to be run without
|
||||
any disadvantages.
|
||||
*/
|
||||
|
||||
|
||||
class PasswordBase
|
||||
{
|
||||
public:
|
||||
static const int HASH_BITS = 256;
|
||||
static const int HASH_BYTES = HASH_BITS / 8;
|
||||
static const int STRENGTHENING_FACTOR = 1000;
|
||||
};
|
||||
|
||||
|
||||
class PasswordCreator : public PasswordBase
|
||||
{
|
||||
public:
|
||||
// Hash a password for transmission to the server during account creation or login
|
||||
// NOTE: You should make the name all lowercase before passing it in
|
||||
// Returns false on failure
|
||||
bool HashPassword(const void *in_name, int name_bytes,
|
||||
const void *in_password, int password_bytes,
|
||||
void *out_hash /* 32 bytes */);
|
||||
|
||||
// This version accepts non-unicode C strings with nul-terminators
|
||||
// It converts the name to lowercase internally
|
||||
bool HashPasswordString(const char *in_name,
|
||||
const char *in_password,
|
||||
void *out_hash /* 32 bytes */);
|
||||
};
|
||||
|
||||
class PasswordVerifier : public PasswordBase
|
||||
{
|
||||
public:
|
||||
// Salt a hash for storage in the account database during account creation
|
||||
// Generates a 32-bit salt and a 256-bit hash for storage
|
||||
// Returns false on failure
|
||||
bool SaltHash(IRandom *prng,
|
||||
const void *in_hash /* 32 bytes */,
|
||||
void *out_salted_hash /* 32 bytes */,
|
||||
u32 *out_salt /* 4 bytes */);
|
||||
|
||||
// Given the stored salted hash and salt, verify the client's password hash during login
|
||||
// Returns false if password is incorrect
|
||||
bool VerifyHash(const void *in_hash /* 32 bytes */,
|
||||
const void *in_salted_hash /* 32 bytes */,
|
||||
u32 in_salt /* 4 bytes */);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_PASSWORDS_HPP
|
||||
222
DependentExtensions/cat/crypt/rand/Fortuna.hpp
Normal file
222
DependentExtensions/cat/crypt/rand/Fortuna.hpp
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on Fortuna algorithm from "Practical Cryptography" section 10.3
|
||||
Published 2003 by Niels Ferguson and Bruce Schneier
|
||||
|
||||
Fortuna supplements the operating system (OS) pseudo-random number generator (PRNG)
|
||||
by incorporating additional entropy into the seeds that the OS provides.
|
||||
|
||||
Modified for use with Skein in PRNG mode, sharing the strengths of both algorithms.
|
||||
|
||||
My implementation of Fortuna (call it Cat For Tuna) has the following components:
|
||||
|
||||
+ Entropy Pools
|
||||
+ 32 pools numbered 0..31
|
||||
+ Implemented as 32 instances of the 256-bit Skein hash
|
||||
+ Entropy hashed into pools in a round-robin fashion
|
||||
+ Scheme allows for recovery against attacker with knowledge of some sources
|
||||
|
||||
+ Entropy Sources
|
||||
+ Uses best OS random number generator
|
||||
+ And a variable number of OS-dependent entropy sources
|
||||
+ Mainly cycle counts and other timing information
|
||||
|
||||
+ Output Generator
|
||||
+ Implemented as a 512-bit Skein hash of some combination of the entropy pools
|
||||
+ The output is produced by the PRNG mode of Skein keyed by the pools
|
||||
+ Hashing all of these pools together and keying the output is called "seeding"
|
||||
+ Reseeded after sufficient entropy has been collected in pool 0
|
||||
+ Pool 0 is always used for reseeding
|
||||
+ Reseed X uses pools numbered by the 1-bits in X (except MSB)
|
||||
+ Previous seed keys the next seed
|
||||
+ Diverges from normal Fortuna due to use of Skein instead of a block cipher
|
||||
+ Reseeds only once every ~512 seconds
|
||||
+ Does not have a limit of 2^16 output blocks
|
||||
+ Skein-PRNG is guaranteed sufficient security properties anyway
|
||||
|
||||
The Fortuna algorithm is broken up into two objects for efficient thread-safety:
|
||||
|
||||
+ FortunaFactory
|
||||
+ Must be initialized on startup and shut down on shutdown
|
||||
+ Spawns a thread to periodically collect additional entropy
|
||||
+ Can create FortunaOutput objects
|
||||
|
||||
+ FortunaOutput
|
||||
+ Reseeds based on master seed in the FortunaFactory
|
||||
+ Reseeds after master seed is updated
|
||||
+ Provides a unique random stream for each thread that uses Fortuna
|
||||
*/
|
||||
|
||||
#ifndef CAT_FOR_TUNA_HPP
|
||||
#define CAT_FOR_TUNA_HPP
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/Singleton.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
|
||||
|
||||
// Defining CAT_NO_ENTROPY_THREAD will remove dependencies on pthreads and not
|
||||
// run a thread to collect more entropy. This is recommended for low-power targets
|
||||
// and other systems where no thread library is available
|
||||
#if defined(CAT_OS_WINDOWS_CE)
|
||||
# define CAT_NO_ENTROPY_THREAD
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
# include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
# include <cat/threads/Thread.hpp>
|
||||
# include <cat/threads/WaitableFlag.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace cat {
|
||||
|
||||
class FortunaOutput;
|
||||
class FortunaFactory;
|
||||
|
||||
|
||||
// Factory for constructing FortunaOutput objects
|
||||
class FortunaFactory : public Singleton<FortunaFactory>
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
, public Thread
|
||||
#endif
|
||||
{
|
||||
CAT_SINGLETON(FortunaFactory)
|
||||
{
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
friend class FortunaOutput;
|
||||
|
||||
#if defined(CAT_OS_WINDOWS) && !defined(CAT_OS_WINDOWS_CE)
|
||||
|
||||
typedef LONG (WINAPI *PtNtQuerySystemInformation)(
|
||||
int SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
HANDLE CurrentProcess;
|
||||
HMODULE NTDLL;
|
||||
PtNtQuerySystemInformation NtQuerySystemInformation;
|
||||
HCRYPTPROV hCryptProv;
|
||||
|
||||
#elif defined(CAT_OS_WINDOWS_CE)
|
||||
|
||||
HCRYPTPROV hCryptProv;
|
||||
|
||||
#elif defined(CAT_OS_LINUX)
|
||||
|
||||
int urandom_fd;
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
static const int ENTROPY_THREAD_KILL_TIMEOUT = 10000; // 10 seconds
|
||||
|
||||
WaitableFlag _kill_flag;
|
||||
|
||||
bool ThreadFunction(void *param);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
static const int ENTROPY_POOLS = 32; // Setting this higher would break something
|
||||
static const int POOL_BITS = 512;
|
||||
static const int POOL_BYTES = POOL_BITS / 8;
|
||||
static const int POOL_QWORDS = POOL_BYTES / sizeof(u64);
|
||||
|
||||
static u32 MasterSeedRevision; // Should not roll over for 13 years if incremented once every RESEED_MIN_TIME
|
||||
static Skein MasterSeed;
|
||||
|
||||
bool _initialized;
|
||||
u32 reseed_counter;
|
||||
Skein Pool[ENTROPY_POOLS];
|
||||
|
||||
bool Reseed();
|
||||
void GetNextKey(FortunaOutput *output);
|
||||
bool InitializeEntropySources();
|
||||
void PollInvariantSources(int pool);
|
||||
void PollSlowEntropySources(int pool);
|
||||
void PollFastEntropySources(int pool);
|
||||
void ShutdownEntropySources();
|
||||
|
||||
public:
|
||||
// Start the entropy generator
|
||||
bool Initialize();
|
||||
|
||||
// Stop the entropy generator
|
||||
void Shutdown();
|
||||
|
||||
// Create a new Fortuna object
|
||||
static FortunaOutput *Create();
|
||||
};
|
||||
|
||||
|
||||
// LoopThread-safe output object for Fortuna
|
||||
class FortunaOutput : public IRandom
|
||||
{
|
||||
friend class FortunaFactory;
|
||||
|
||||
static const int OUTPUT_CACHE_BYTES = FortunaFactory::POOL_BYTES * 8; // Arbitrary
|
||||
|
||||
u32 thread_id, SeedRevision;
|
||||
Skein OutputHash;
|
||||
u8 CachedRandomBytes[OUTPUT_CACHE_BYTES];
|
||||
int used_bytes;
|
||||
|
||||
void Reseed();
|
||||
|
||||
FortunaOutput();
|
||||
FortunaOutput(FortunaOutput&) {}
|
||||
FortunaOutput &operator=(FortunaOutput &) { return *this; }
|
||||
|
||||
public:
|
||||
~FortunaOutput();
|
||||
|
||||
// Generate a 32-bit random number
|
||||
u32 Generate();
|
||||
|
||||
// Generate a variable number of random bytes
|
||||
void Generate(void *buffer, int bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_FOR_TUNA_HPP
|
||||
145
DependentExtensions/cat/crypt/symmetric/ChaCha.hpp
Normal file
145
DependentExtensions/cat/crypt/symmetric/ChaCha.hpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
The ChaCha cipher is a symmetric stream cipher based on Salsa20.
|
||||
http://cr.yp.to/chacha.html
|
||||
*/
|
||||
|
||||
#ifndef CAT_CHACHA_HPP
|
||||
#define CAT_CHACHA_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
/*
|
||||
To initialize the ChaCha cipher, you must specify a 256-bit key.
|
||||
|
||||
Code example:
|
||||
|
||||
ChaChaKey cck;
|
||||
char key[32]; // fill key here
|
||||
|
||||
cck.Key(key, sizeof(key));
|
||||
|
||||
Before each encryption or decryption with the ChaCha cipher,
|
||||
a 64-bit Initialization Vector (IV) must be specified. Every
|
||||
time a message is encrypted, the IV must be incremented by 1.
|
||||
The IV is then sent along with the encrypted message.
|
||||
|
||||
Encryption code example:
|
||||
|
||||
char message[19], ciphertext[19]; // message filled here
|
||||
u64 iv = 125125;
|
||||
u64 message_iv = iv;
|
||||
iv = iv + 1;
|
||||
|
||||
ChaChaOutput cco(cck, message_iv);
|
||||
cco.Crypt(message, ciphertext, sizeof(ciphertext));
|
||||
|
||||
Decryption code example:
|
||||
|
||||
char ciphertext[19], decrypted[19]; // ciphertext filled here
|
||||
|
||||
ChaChaOutput cco(cck, message_iv);
|
||||
cco.Crypt(ciphertext, decrypted, sizeof(decrypted));
|
||||
|
||||
Sending all 8 bytes of the IV in every packet is not necessary.
|
||||
Instead, only a few of the low bits of the IV need to be sent,
|
||||
if the IV is incremented by 1 each time.
|
||||
|
||||
How many? It depends on how many messages can get lost.
|
||||
If < 32768 messages can get lost in a row, then CAT_IV_BITS = 16 (default)
|
||||
|
||||
I have provided a function to handle rollover/rollunder of the IV,
|
||||
which also works if the same IV is sent twice for some reason.
|
||||
It needs to know how many of the low bits are sent across, so be sure
|
||||
to change CAT_IV_BITS in this header if you send more or less than 16.
|
||||
|
||||
Code example:
|
||||
|
||||
u64 last_accepted_iv;
|
||||
u32 new_iv_low_bits;
|
||||
|
||||
u64 new_iv = ChaCha::ReconstructIV(last_accepted_iv, new_iv_low_bits);
|
||||
|
||||
-------------------------READ THIS BEFORE USING--------------------------
|
||||
|
||||
Never use the same IV twice.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
Never use the same key twice.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
If you have two hosts talking to eachother securely with ChaCha encryption,
|
||||
then be sure that each host is encrypting with a DIFFERENT key.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
Remember that an attacker can impersonate the remote computer, so be
|
||||
sure not to accept the new IV until the message authentication code has
|
||||
been verified if your protocol uses a message authentication code (MAC).
|
||||
Otherwise: An attacker could desynchronize the IVs.
|
||||
*/
|
||||
|
||||
|
||||
//// ChaChaKey
|
||||
|
||||
class CAT_EXPORT ChaChaKey
|
||||
{
|
||||
friend class ChaChaOutput;
|
||||
u32 state[16];
|
||||
|
||||
public:
|
||||
~ChaChaKey();
|
||||
|
||||
// Key up to 384 bits
|
||||
void Set(const void *key, int bytes);
|
||||
};
|
||||
|
||||
|
||||
//// ChaChaOutput
|
||||
|
||||
class CAT_EXPORT ChaChaOutput
|
||||
{
|
||||
u32 state[16];
|
||||
|
||||
void GenerateKeyStream(u32 *out);
|
||||
|
||||
public:
|
||||
ChaChaOutput(const ChaChaKey &key, u64 iv);
|
||||
~ChaChaOutput();
|
||||
|
||||
// Message with any number of bytes
|
||||
void Crypt(const void *in, void *out, int bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_CHACHA_HPP
|
||||
148
DependentExtensions/cat/crypt/tunnel/AuthenticatedEncryption.hpp
Normal file
148
DependentExtensions/cat/crypt/tunnel/AuthenticatedEncryption.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
#define CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
|
||||
#include <cat/crypt/symmetric/ChaCha.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/crypt/hash/HMAC_MD5.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Tunnel Authenticated Encryption "Calico" protocol:
|
||||
|
||||
Run after the Key Agreement protocol completes.
|
||||
Uses a 1024-bit anti-replay sliding window, suitable for Internet file transfer over UDP.
|
||||
|
||||
Cipher: 12-round ChaCha with 256-bit or 384-bit keys
|
||||
KDF: Key derivation function (Skein)
|
||||
MAC: 64-bit truncated HMAC-MD5
|
||||
IV: Initialization vector incrementing by 1 each time
|
||||
|
||||
c2sMKey = KDF(k) { "upstream-MAC" }
|
||||
s2cMKey = KDF(k) { "downstream-MAC" }
|
||||
c2sEKey = KDF(k) { "upstream-ENC" }
|
||||
s2cEKey = KDF(k) { "downstream-ENC" }
|
||||
c2sIV = KDF(k) { "upstream-IV" }
|
||||
s2cIV = KDF(k) { "downstream-IV" }
|
||||
|
||||
To transmit a message, the client calculates a MAC with the c2sMKey of the IV concatenated with
|
||||
the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
|
||||
which is encrypted using the c2sEKey and the IV.
|
||||
|
||||
c2s Encrypt(c2sEKey) { message || MAC(c2sMKey) { full-iv-us||message } } || Obfuscated { trunc-iv-us }
|
||||
|
||||
encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
|
||||
|
||||
To transmit a message, the server calculates a MAC with the s2cMKey of the IV concatenated with
|
||||
the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
|
||||
which is encrypted using the s2cEKey and the IV.
|
||||
|
||||
s2c Encrypt(s2cEKey) { message || MAC(s2cMKey) { full-iv-ds||message } } || Obfuscated { trunc-iv-ds }
|
||||
|
||||
encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
|
||||
|
||||
The full 64-bit IVs are initialized to c2sIV and s2cIV, and the first one sent is IV+1.
|
||||
*/
|
||||
|
||||
|
||||
class KeyAgreementResponder;
|
||||
class KeyAgreementInitiator;
|
||||
|
||||
|
||||
// This class is NOT THREAD-SAFE.
|
||||
class CAT_EXPORT AuthenticatedEncryption
|
||||
{
|
||||
friend class KeyAgreementResponder;
|
||||
friend class KeyAgreementInitiator;
|
||||
|
||||
bool _is_initiator, _accept_out_of_order;
|
||||
Skein key_hash;
|
||||
|
||||
HMAC_MD5 local_mac_key, remote_mac_key;
|
||||
ChaChaKey local_cipher_key, remote_cipher_key;
|
||||
u64 local_iv, remote_iv;
|
||||
|
||||
// 1024-bit anti-replay sliding window
|
||||
static const int BITMAP_BITS = 1024;
|
||||
static const int BITMAP_WORDS = BITMAP_BITS / 64;
|
||||
u64 iv_bitmap[BITMAP_WORDS];
|
||||
|
||||
public:
|
||||
CAT_INLINE AuthenticatedEncryption() {}
|
||||
CAT_INLINE ~AuthenticatedEncryption() {}
|
||||
|
||||
// Tunnel overhead bytes
|
||||
static const int MAC_BYTES = 8;
|
||||
static const int IV_BYTES = 3;
|
||||
static const u32 OVERHEAD_BYTES = IV_BYTES + MAC_BYTES;
|
||||
|
||||
// IV constants
|
||||
static const int IV_BITS = IV_BYTES * 8;
|
||||
static const u32 IV_MSB = (1 << IV_BITS);
|
||||
static const u32 IV_MASK = (IV_MSB - 1);
|
||||
static const u32 IV_FUZZ = 0xCA7DCA7D;
|
||||
|
||||
protected:
|
||||
bool SetKey(int KeyBytes, Skein *key, bool is_initiator, const char *key_name);
|
||||
|
||||
bool IsValidIV(u64 iv);
|
||||
void AcceptIV(u64 iv);
|
||||
|
||||
public:
|
||||
// Generate a proof that the local host has the key
|
||||
bool GenerateProof(u8 *local_proof, int proof_bytes);
|
||||
|
||||
// Validate a proof that the remote host has the key
|
||||
bool ValidateProof(const u8 *remote_proof, int proof_bytes);
|
||||
|
||||
public:
|
||||
void AllowOutOfOrder(bool allowed = true) { _accept_out_of_order = allowed; }
|
||||
|
||||
public:
|
||||
// Overhead is OVERHEAD_BYTES bytes at the end of the packet
|
||||
// Returns false if the message is invalid. Invalid messages should just be ignored as if they were never received
|
||||
// buf_bytes: Number of bytes in the buffer, including the overhead
|
||||
// If Decrypt() returns true, buf_bytes is set to the size of the decrypted message
|
||||
bool Decrypt(u8 *buffer, u32 &buf_bytes);
|
||||
|
||||
// Overhead is OVERHEAD_BYTES bytes at the end of the packet
|
||||
// buffer_bytes: Number of bytes in the buffer; will return false if buffer size too small
|
||||
// msg_bytes: Number of bytes in the message, excluding the overhead
|
||||
// If Encrypt() returns true, msg_bytes is set to the size of the encrypted message
|
||||
bool Encrypt(u8 *buffer, u32 buffer_bytes, u32 &msg_bytes);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
307
DependentExtensions/cat/crypt/tunnel/EasyHandshake.hpp
Normal file
307
DependentExtensions/cat/crypt/tunnel/EasyHandshake.hpp
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_EASY_HANDSHAKE_HPP
|
||||
#define CAT_EASY_HANDSHAKE_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreementInitiator.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementResponder.hpp>
|
||||
#include <cat/crypt/cookie/CookieJar.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
The EasyHandshake classes implement a simplified version of my Tunnel protocol.
|
||||
|
||||
This only works for single-threaded servers and only produces a single authenticated encryption
|
||||
object for each handshake. Explanations on how to use the library with a multi-threaded
|
||||
server, and how to use one handshake to secure several TCP streams, are documented in the
|
||||
comments of these classes.
|
||||
|
||||
|
||||
Over the network, the handshake will look like this:
|
||||
|
||||
client --> server : CHALLENGE (64 random-looking bytes)
|
||||
|
||||
server --> client : ANSWER (128 random-looking bytes)
|
||||
|
||||
client --> server : PROOF (32 random-looking bytes) + first encrypted packet can be appended here
|
||||
|
||||
|
||||
As far as coding goes, the function calls fit into the protocol like this:
|
||||
|
||||
server is offline:
|
||||
|
||||
During startup, both the client and server should initialize the library.
|
||||
This is necessary also just for generating keys:
|
||||
----------------------------------------------------------------
|
||||
#include <cat/AllTunnel.hpp>
|
||||
using namespace cat;
|
||||
|
||||
if (!EasyHandshake::Initialize())
|
||||
{
|
||||
printf("ERROR:Unable to initialize crypto subsystem\n");
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
Generate the server public and private key pairs:
|
||||
----------------------------------------------------------------
|
||||
u8 public_key[EasyHandshake::PUBLIC_KEY_BYTES];
|
||||
u8 private_key[EasyHandshake::PRIVATE_KEY_BYTES];
|
||||
|
||||
EasyHandshake temp;
|
||||
temp.GenerateServerKey(public_key, private_key);
|
||||
----------------------------------------------------------------
|
||||
|
||||
(keys are stored to disk for reading on start-up)
|
||||
|
||||
(public key is given to the client somehow)
|
||||
+ built into the client code
|
||||
+ provided by a trusted server
|
||||
|
||||
server comes online:
|
||||
|
||||
----------------------------------------------------------------
|
||||
ServerEasyHandshake server_handshake;
|
||||
|
||||
server_handshake.Initialize(public_key, private_key);
|
||||
----------------------------------------------------------------
|
||||
|
||||
client comes online:
|
||||
|
||||
----------------------------------------------------------------
|
||||
ClientEasyHandshake client_handshake;
|
||||
|
||||
client_handshake.Initialize(public_key);
|
||||
|
||||
u8 challenge[EasyHandshake::CHALLENGE_BYTES];
|
||||
|
||||
client_handshake.GenerateChallenge(challenge);
|
||||
----------------------------------------------------------------
|
||||
|
||||
client --> server : CHALLENGE (64 random-looking bytes)
|
||||
|
||||
----------------------------------------------------------------
|
||||
AuthenticatedEncryption server_e;
|
||||
|
||||
u8 answer[EasyHandshake::ANSWER_BYTES];
|
||||
|
||||
server_handshake.ProcessChallenge(challenge, answer, &server_e);
|
||||
----------------------------------------------------------------
|
||||
|
||||
server --> client : ANSWER (128 random-looking bytes)
|
||||
|
||||
----------------------------------------------------------------
|
||||
AuthenticatedEncryption client_e;
|
||||
|
||||
client_handshake.ProcessAnswer(answer, &client_e);
|
||||
|
||||
u8 proof[EasyHandshake::PROOF_BYTES];
|
||||
|
||||
client_e.GenerateProof(proof, EasyHandshake::PROOF_BYTES);
|
||||
----------------------------------------------------------------
|
||||
|
||||
Encryption example:
|
||||
----------------------------------------------------------------
|
||||
// Example message encryption of "Hello". Note that encryption
|
||||
// inflates the size of the message by OVERHEAD_BYTES.
|
||||
const int PLAINTEXT_BYTES = 5;
|
||||
const int BUFFER_BYTES = \
|
||||
PLAINTEXT_BYTES + AuthenticatedEncryption::OVERHEAD_BYTES;
|
||||
int msg_bytes = PLAINTEXT_BYTES;
|
||||
|
||||
// Note that it makes room for message inflation
|
||||
const u8 message[CIPHERTEXT_BYTES] = {
|
||||
'H', 'e', 'l', 'l', 'o'
|
||||
};
|
||||
|
||||
// Note the second parameter is the size of the buffer, and
|
||||
// the third parameter will be adjusted to the size of the
|
||||
// encrypted message:
|
||||
|
||||
if (client_e.Encrypt(message, BUFFER_BYTES, msg_bytes))
|
||||
{
|
||||
// msg_bytes is now adjusted to be the size of the ciphertext
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
client --> server : PROOF (32 random-looking bytes) + first encrypted packet can be appended here
|
||||
|
||||
----------------------------------------------------------------
|
||||
server_e.ValidateProof(proof, EasyHandshake::PROOF_BYTES);
|
||||
----------------------------------------------------------------
|
||||
|
||||
Decryption example:
|
||||
----------------------------------------------------------------
|
||||
int buf_bytes = msg_bytes;
|
||||
|
||||
// The second parameter is the number of bytes in the encrypted message
|
||||
if (server_e.Decrypt(message, buf_bytes))
|
||||
{
|
||||
// buf_bytes is now adjusted to be the size of the plaintext
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
During program termination, the client and server should clean up:
|
||||
----------------------------------------------------------------
|
||||
EasyHandshake::Shutdown();
|
||||
----------------------------------------------------------------
|
||||
|
||||
NOTES:
|
||||
|
||||
Once the authenticated encryption objects are created, if the messages received are always
|
||||
guaranteed to be in order, then the following flag can be set to make the object reject
|
||||
packets received out of order, which would indicate tampering:
|
||||
auth_enc.AllowOutOfOrder(false);
|
||||
By default the messages are assumed to arrive in any order up to 1024 messages out of order.
|
||||
|
||||
The server similarly can encrypt messages the same way the client does in the examples.
|
||||
|
||||
Encrypted messages are inflated by 11 random-looking bytes for a MAC and an IV.
|
||||
Modifications to the code can allow lower overhead if needed.
|
||||
|
||||
The EasyHandshake classes are *NOT* THREAD-SAFE.
|
||||
|
||||
The AuthenticatedEncryption class is *NOT* THREAD-SAFE. Simultaneously, only ONE thread
|
||||
can be encrypting messages. And only ONE thread can be decrypting messages. Encryption
|
||||
and decryption are separate and safe to perform simultaneously.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Common data needed for handshaking
|
||||
*/
|
||||
class CAT_EXPORT EasyHandshake
|
||||
{
|
||||
protected:
|
||||
// Normally these would be created per-thread.
|
||||
// To free memory associated with these objects just delete them.
|
||||
BigTwistedEdwards *tls_math;
|
||||
FortunaOutput *tls_csprng;
|
||||
|
||||
public:
|
||||
static const int BITS = 256;
|
||||
static const int BYTES = BITS / 8;
|
||||
static const int PUBLIC_KEY_BYTES = BYTES * 2;
|
||||
static const int PRIVATE_KEY_BYTES = BYTES;
|
||||
static const int CHALLENGE_BYTES = BYTES * 2; // Packet # 1 in handshake, sent to server
|
||||
static const int ANSWER_BYTES = BYTES * 4; // Packet # 2 in handshake, sent to client
|
||||
static const int PROOF_BYTES = BYTES; // Packet # 3 in handshake, sent to server
|
||||
static const int IDENTITY_BYTES = BYTES * 5; // [optional] Packet # 3 in handshake, sent to server, proves identity of client also
|
||||
|
||||
public:
|
||||
// Demonstrates how to allocate and free the math and prng objects
|
||||
EasyHandshake();
|
||||
~EasyHandshake();
|
||||
|
||||
public:
|
||||
static bool Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
public:
|
||||
// Generate a server (public, private) key pair
|
||||
// Connecting clients will need to know the public key in order to connect
|
||||
bool GenerateServerKey(void *out_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
void *out_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Fills the given buffer with a variable number of random bytes
|
||||
// Returns false on failure
|
||||
bool GenerateRandomNumber(void *out_num, int bytes);
|
||||
};
|
||||
|
||||
/*
|
||||
Implements the simple case of a server that performs handshakes with clients
|
||||
from a single thread. Note that this implementation is not thread-safe.
|
||||
*/
|
||||
class CAT_EXPORT ServerEasyHandshake : public EasyHandshake
|
||||
{
|
||||
KeyAgreementResponder tun_server;
|
||||
|
||||
public:
|
||||
ServerEasyHandshake();
|
||||
~ServerEasyHandshake();
|
||||
|
||||
// Prepare a cookie jar for hungry consumers
|
||||
void FillCookieJar(CookieJar *jar);
|
||||
|
||||
// Provide the public and private key for the server, previously generated offline
|
||||
bool Initialize(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
const void *in_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Process a client challenge and generate a server answer
|
||||
// Returns false if challenge was invalid
|
||||
bool ProcessChallenge(const void *in_challenge /* EasyHandshake::CHALLENGE_BYTES */,
|
||||
void *out_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
|
||||
// Validate a client proof of identity
|
||||
// Returns false if proof was invalid
|
||||
bool VerifyInitiatorIdentity(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
const void *in_proof /* EasyHandshake::IDENTITY_BYTES */,
|
||||
void *out_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */);
|
||||
};
|
||||
|
||||
/*
|
||||
Implements the simple case of a client that performs handshakes with servers
|
||||
from a single thread. Note that this implementation is not thread-safe.
|
||||
*/
|
||||
class CAT_EXPORT ClientEasyHandshake : public EasyHandshake
|
||||
{
|
||||
KeyAgreementInitiator tun_client;
|
||||
|
||||
public:
|
||||
ClientEasyHandshake();
|
||||
~ClientEasyHandshake();
|
||||
|
||||
// Provide the public key for the server, acquired through some secure means
|
||||
bool Initialize(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */);
|
||||
|
||||
// (optional) Provide the identity for the client
|
||||
bool SetIdentity(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
const void *in_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Generate a challenge for the server to answer
|
||||
bool GenerateChallenge(void *out_challenge /* EasyHandshake::CHALLENGE_BYTES */);
|
||||
|
||||
// Process a server answer to our challenge
|
||||
// Returns false if answer was invalid
|
||||
bool ProcessAnswer(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
|
||||
// Process a server answer to our challenge and provide a proof of client identity
|
||||
// Returns false if answer was invalid
|
||||
bool ProcessAnswerWithIdentity(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
void *out_identity /* EasyHandshake::IDENTITY_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_EASY_HANDSHAKE_HPP
|
||||
210
DependentExtensions/cat/crypt/tunnel/KeyAgreement.hpp
Normal file
210
DependentExtensions/cat/crypt/tunnel/KeyAgreement.hpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_HPP
|
||||
#define CAT_KEY_AGREEMENT_HPP
|
||||
|
||||
#include <cat/math/BigTwistedEdwards.hpp>
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Tunnel Key Agreement "Tabby" protocol:
|
||||
An unauthenticated Diffie-Hellman key agreement protocol with forward secrecy
|
||||
Immune to active attacks (man-in-the-middle) if server key is known ahead of time
|
||||
|
||||
Using Elliptic Curve Cryptography over finite field Fp, p = 2^n - c, c small
|
||||
Shape of curve: a' * x^2 + y^2 = 1 + d' * x^2 * y^2, a' = -1 (square in Fp)
|
||||
d' (non square in Fp) -> order of curve = q * cofactor h, order of generator point = q
|
||||
Curves satisfy MOV conditions and are not anomalous
|
||||
Point operations performed with Extended Twisted Edwards group laws
|
||||
See BigTwistedEdwards.hpp for more information
|
||||
|
||||
H: Skein-Key, either 256-bit or 512-bit based on security level
|
||||
MAC: Skein-MAC, keyed from output of H()
|
||||
|
||||
Here the protocol initiator is the (c)lient, and the responder is the (s)erver:
|
||||
|
||||
s: long-term private key 1 < b < q, long-term public key B = b * G
|
||||
|
||||
256-bit security: B = 64 bytes for public key, b = 32 bytes for private key
|
||||
384-bit security: B = 96 bytes for public key, b = 48 bytes for private key
|
||||
512-bit security: B = 128 bytes for public key, b = 64 bytes for private key
|
||||
|
||||
c: Client already knows the server's public key B before Key Agreement
|
||||
c: ephemeral private key 1 < a < q, ephemeral public key A = a * G
|
||||
|
||||
Initiator Challenge: c2s A
|
||||
|
||||
256-bit security: A = 64 bytes
|
||||
384-bit security: A = 96 bytes
|
||||
512-bit security: A = 128 bytes
|
||||
|
||||
s: validate A, ignore invalid
|
||||
Invalid A(x,y) would be the additive identity x=0 or any point not on the curve
|
||||
|
||||
s: ephemeral private key 1 < y < q, ephemeral public key Y = y * G
|
||||
Ephemeral key is re-used for several connections before being regenerated
|
||||
|
||||
s: hA = h * A
|
||||
s: random n-bit number r
|
||||
s: d = H(A,B,Y,r)
|
||||
Repeat the previous two steps until d >= 1000
|
||||
|
||||
s: e = b + d*y (mod q)
|
||||
s: T = AffineX(e * hA)
|
||||
s: k = H(d,T)
|
||||
|
||||
Responder Answer: s2c Y || r || MAC(k) {"responder proof"}
|
||||
|
||||
256-bit security: Y(64by) r(32by) MAC(32by) = 128 bytes
|
||||
384-bit security: Y(96by) r(48by) MAC(48by) = 192 bytes
|
||||
512-bit security: Y(128by) r(64by) MAC(64by) = 256 bytes
|
||||
|
||||
c: validate Y, ignore invalid
|
||||
Invalid Y(x,y) would be the additive identity x=0 or any point not on the curve
|
||||
|
||||
c: hY = h * Y
|
||||
c: d = H(A,B,Y,r)
|
||||
c: Verify d >= 1000
|
||||
c: T = AffineX(a * hB + d*a * hY)
|
||||
c: k = H(d,T)
|
||||
|
||||
c: validate MAC, ignore invalid
|
||||
|
||||
Initiator Proof: c2s MAC(k) {"initiator proof"}
|
||||
|
||||
This packet can also include the client's first encrypted message
|
||||
|
||||
256-bit security: MAC(32by) = 32 bytes
|
||||
384-bit security: MAC(48by) = 48 bytes
|
||||
512-bit security: MAC(64by) = 64 bytes
|
||||
|
||||
s: validate MAC, ignore invalid
|
||||
|
||||
Notes:
|
||||
|
||||
The strategy of this protocol is to perform two EC Diffie-Hellman exchanges,
|
||||
one with the long-term server key and the second with an ephemeral key that
|
||||
should be much harder to obtain by an attacker. The resulting two shared
|
||||
secret points are added together into one point that is used for the key.
|
||||
|
||||
It is perfectly acceptable to re-use an ephemeral key for several runs of
|
||||
the protocol. This means that most of the processing done by the server is
|
||||
just one point multiplication.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Schnorr signatures:
|
||||
|
||||
For signing, the signer reuses its Key Agreement key pair (b,B)
|
||||
|
||||
H: Skein-Key, either 256-bit or 512-bit based on security level
|
||||
|
||||
To sign a message M, signer computes:
|
||||
|
||||
ephemeral secret random 1 < k < q, ephemeral point K = k * G
|
||||
e = H(M || K)
|
||||
s = k - b*e (mod q)
|
||||
|
||||
This process is repeated until e and s are non-zero
|
||||
|
||||
Signature: s2c e || s
|
||||
|
||||
256-bit security: e(32by) s(32by) = 64 bytes
|
||||
384-bit security: e(48by) s(48by) = 96 bytes
|
||||
512-bit security: e(64by) s(64by) = 128 bytes
|
||||
|
||||
To verify a signature:
|
||||
|
||||
Check e, s are in the range [1,q-1]
|
||||
|
||||
K' = s*G + e*B
|
||||
e' = H(M || K')
|
||||
|
||||
The signature is verified if e == e'
|
||||
|
||||
Notes:
|
||||
|
||||
K ?= K'
|
||||
= s*G + e*B
|
||||
= (k - b*e)*G + e*(b*G)
|
||||
= k*G - b*e*G + e*b*G
|
||||
= K
|
||||
*/
|
||||
|
||||
|
||||
// If CAT_DETERMINISTIC_KEY_GENERATION is undefined, the time to generate a
|
||||
// key is unbounded, but tends to be 1 try. I think this is a good thing
|
||||
// because it randomizes the runtime and helps avoid timing attacks
|
||||
//#define CAT_DETERMINISTIC_KEY_GENERATION
|
||||
|
||||
// If CAT_USER_ERROR_CHECKING is defined, the key agreement objects will
|
||||
// check to make sure that the input parameters are all the right length
|
||||
// and that the math and prng objects are not null
|
||||
#define CAT_USER_ERROR_CHECKING
|
||||
|
||||
class CAT_EXPORT KeyAgreementCommon
|
||||
{
|
||||
public:
|
||||
static BigTwistedEdwards *InstantiateMath(int bits);
|
||||
|
||||
// Math library register usage
|
||||
static const int ECC_REG_OVERHEAD = 21;
|
||||
|
||||
// c: field prime modulus p = 2^bits - C, p = 5 mod 8 s.t. a=-1 is a square in Fp
|
||||
// d: curve coefficient (yy-xx=1+Dxxyy), not a square in Fp
|
||||
static const int EDWARD_C_256 = 435;
|
||||
static const int EDWARD_D_256 = 31720;
|
||||
static const int EDWARD_C_384 = 2147;
|
||||
static const int EDWARD_D_384 = 13036;
|
||||
static const int EDWARD_C_512 = 875;
|
||||
static const int EDWARD_D_512 = 32;
|
||||
|
||||
// Limits on field prime
|
||||
static const int MAX_BITS = 512;
|
||||
static const int MAX_BYTES = MAX_BITS / 8;
|
||||
static const int MAX_LEGS = MAX_BYTES / sizeof(Leg);
|
||||
|
||||
protected:
|
||||
int KeyBits, KeyBytes, KeyLegs;
|
||||
|
||||
bool Initialize(int bits);
|
||||
|
||||
public:
|
||||
// Generates an unbiased random key in the range 1 < key < q
|
||||
void GenerateKey(BigTwistedEdwards *math, IRandom *prng, Leg *key);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_HPP
|
||||
101
DependentExtensions/cat/crypt/tunnel/KeyAgreementInitiator.hpp
Normal file
101
DependentExtensions/cat/crypt/tunnel/KeyAgreementInitiator.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
#define CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT KeyAgreementInitiator : public KeyAgreementCommon
|
||||
{
|
||||
Leg *B; // Responder's public key (pre-shared with initiator)
|
||||
Leg *a; // Initiator's private key (kept secret)
|
||||
Leg *A; // Initiator's public key (shared with responder in Challenge message)
|
||||
Leg *hB; // h*B
|
||||
Leg *G_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *B_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *Y_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *A_neutral; // Endian-neutral A
|
||||
Leg *B_neutral; // Endian-neutral B
|
||||
|
||||
// Identity data
|
||||
Leg *I_private; // Initiator's identity private key
|
||||
Leg *I_public; // Endian-neutral initiator's identity public key
|
||||
|
||||
bool AllocateMemory();
|
||||
void FreeMemory();
|
||||
|
||||
public:
|
||||
KeyAgreementInitiator();
|
||||
~KeyAgreementInitiator();
|
||||
|
||||
bool Initialize(BigTwistedEdwards *math,
|
||||
const u8 *responder_public_key, int public_bytes);
|
||||
|
||||
// Call after Initialize()
|
||||
bool SetIdentity(BigTwistedEdwards *math,
|
||||
const u8 *initiator_public_key, int public_bytes,
|
||||
const u8 *initiator_private_key, int private_bytes);
|
||||
|
||||
public:
|
||||
bool GenerateChallenge(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
u8 *initiator_challenge, int challenge_bytes);
|
||||
|
||||
bool ProcessAnswer(BigTwistedEdwards *math,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
Skein *key_hash);
|
||||
|
||||
// Will fail if SetIdentity() has not been called
|
||||
bool ProcessAnswerWithIdentity(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
Skein *key_hash,
|
||||
u8 *identity_proof, int proof_bytes);
|
||||
|
||||
CAT_INLINE bool KeyEncryption(Skein *key_hash, AuthenticatedEncryption *auth_enc, const char *key_name)
|
||||
{
|
||||
return auth_enc->SetKey(KeyBytes, key_hash, true, key_name);
|
||||
}
|
||||
|
||||
// Erase the private key after handshake completes
|
||||
// Also done as this object is destroyed
|
||||
void SecureErasePrivateKey();
|
||||
|
||||
public:
|
||||
bool Verify(BigTwistedEdwards *math,
|
||||
const u8 *message, int message_bytes,
|
||||
const u8 *signature, int signature_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
#define CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
#include <cat/threads/Atomic.hpp>
|
||||
|
||||
#if defined(CAT_NO_ATOMIC_ADD) || defined(CAT_NO_ATOMIC_SET)
|
||||
# include <cat/threads/Mutex.hpp>
|
||||
# define CAT_NO_ATOMIC_RESPONDER
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT KeyAgreementResponder : public KeyAgreementCommon
|
||||
{
|
||||
Leg *b; // Responder's private key (kept secret)
|
||||
Leg *B; // Responder's public key (pre-shared with initiator)
|
||||
Leg *B_neutral; // Endian-neutral B
|
||||
Leg *G_MultPrecomp; // 8-bit table for multiplication
|
||||
Leg *y[2]; // Responder's ephemeral private key (kept secret)
|
||||
Leg *Y_neutral[2]; // Responder's ephemeral public key (shared online with initiator)
|
||||
|
||||
#if defined(CAT_NO_ATOMIC_RESPONDER)
|
||||
Mutex m_thread_id_mutex;
|
||||
#endif // CAT_NO_ATOMIC_RESPONDER
|
||||
|
||||
volatile u32 ChallengeCount;
|
||||
volatile u32 ActiveY;
|
||||
|
||||
void Rekey(BigTwistedEdwards *math, FortunaOutput *csprng);
|
||||
bool AllocateMemory();
|
||||
void FreeMemory();
|
||||
|
||||
public:
|
||||
KeyAgreementResponder();
|
||||
~KeyAgreementResponder();
|
||||
|
||||
bool Initialize(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *responder_public_key, int public_bytes,
|
||||
const u8 *responder_private_key, int private_bytes);
|
||||
|
||||
public:
|
||||
bool ProcessChallenge(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *initiator_challenge, int challenge_bytes,
|
||||
u8 *responder_answer, int answer_bytes, Skein *key_hash);
|
||||
|
||||
inline bool KeyEncryption(Skein *key_hash, AuthenticatedEncryption *auth_enc, const char *key_name)
|
||||
{
|
||||
return auth_enc->SetKey(KeyBytes, key_hash, false, key_name);
|
||||
}
|
||||
|
||||
// Public key is filled if proof succeeds, and will return true
|
||||
bool VerifyInitiatorIdentity(BigTwistedEdwards *math,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
const u8 *proof, int proof_bytes,
|
||||
u8 *public_key, int public_bytes);
|
||||
|
||||
public:
|
||||
bool Sign(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *message, int message_bytes,
|
||||
u8 *signature, int signature_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
47
DependentExtensions/cat/crypt/tunnel/KeyMaker.hpp
Normal file
47
DependentExtensions/cat/crypt/tunnel/KeyMaker.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_MAKER_HPP
|
||||
#define CAT_KEY_MAKER_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class KeyMaker : public KeyAgreementCommon
|
||||
{
|
||||
public:
|
||||
bool GenerateKeyPair(BigTwistedEdwards *math, FortunaOutput *csprng, u8 *public_key, int public_bytes, u8 *private_key, int private_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_MAKER_HPP
|
||||
Reference in New Issue
Block a user