Init
This commit is contained in:
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