This commit is contained in:
2025-11-24 14:19:51 +05:30
commit f5c1412b28
6734 changed files with 1527575 additions and 0 deletions

View 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

View 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

View 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

View 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

View File

@ -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

View 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