Shadowrun: Awakened 29 September 2011 - Build 871
AuthenticatedEncryption.hpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009-2010 Christopher A. Taylor.  All rights reserved.
00003 
00004     Redistribution and use in source and binary forms, with or without
00005     modification, are permitted provided that the following conditions are met:
00006 
00007     * Redistributions of source code must retain the above copyright notice,
00008       this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice,
00010       this list of conditions and the following disclaimer in the documentation
00011       and/or other materials provided with the distribution.
00012     * Neither the name of LibCat nor the names of its contributors may be used
00013       to endorse or promote products derived from this software without
00014       specific prior written permission.
00015 
00016     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00020     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026     POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00029 #ifndef CAT_AUTHENTICATED_ENCRYPTION_HPP
00030 #define CAT_AUTHENTICATED_ENCRYPTION_HPP
00031 
00032 #include <cat/crypt/symmetric/ChaCha.hpp>
00033 #include <cat/crypt/hash/Skein.hpp>
00034 #include <cat/crypt/hash/HMAC_MD5.hpp>
00035 
00036 namespace cat {
00037 
00038 
00039 /*
00040     Tunnel Authenticated Encryption "Calico" protocol:
00041 
00042     Run after the Key Agreement protocol completes.
00043     Uses a 1024-bit anti-replay sliding window, suitable for Internet file transfer over UDP.
00044 
00045     Cipher: 12-round ChaCha with 256-bit or 384-bit keys
00046     KDF: Key derivation function (Skein)
00047     MAC: 64-bit truncated HMAC-MD5
00048     IV: Initialization vector incrementing by 1 each time
00049 
00050     c2sMKey = KDF(k) { "upstream-MAC" }
00051     s2cMKey = KDF(k) { "downstream-MAC" }
00052     c2sEKey = KDF(k) { "upstream-ENC" }
00053     s2cEKey = KDF(k) { "downstream-ENC" }
00054     c2sIV = KDF(k) { "upstream-IV" }
00055     s2cIV = KDF(k) { "downstream-IV" }
00056 
00057     To transmit a message, the client calculates a MAC with the c2sMKey of the IV concatenated with
00058     the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
00059     which is encrypted using the c2sEKey and the IV.
00060 
00061     c2s Encrypt(c2sEKey) { message || MAC(c2sMKey) { full-iv-us||message } } || Obfuscated { trunc-iv-us }
00062 
00063         encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
00064 
00065     To transmit a message, the server calculates a MAC with the s2cMKey of the IV concatenated with
00066     the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
00067     which is encrypted using the s2cEKey and the IV.
00068 
00069     s2c Encrypt(s2cEKey) { message || MAC(s2cMKey) { full-iv-ds||message } } || Obfuscated { trunc-iv-ds }
00070 
00071         encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
00072 
00073     The full 64-bit IVs are initialized to c2sIV and s2cIV, and the first one sent is IV+1.
00074 */
00075 
00076 
00077 class KeyAgreementResponder;
00078 class KeyAgreementInitiator;
00079 
00080 
00081 // This class is NOT THREAD-SAFE.
00082 class AuthenticatedEncryption
00083 {
00084     friend class KeyAgreementResponder;
00085     friend class KeyAgreementInitiator;
00086 
00087     bool _is_initiator, _accept_out_of_order;
00088     Skein key_hash;
00089 
00090     HMAC_MD5 local_mac_key, remote_mac_key;
00091     ChaChaKey local_cipher_key, remote_cipher_key;
00092     u64 local_iv, remote_iv;
00093 
00094     // 1024-bit anti-replay sliding window
00095     static const int BITMAP_BITS = 1024;
00096     static const int BITMAP_WORDS = BITMAP_BITS / 64;
00097     u64 iv_bitmap[BITMAP_WORDS];
00098 
00099 public:
00100     // Tunnel overhead bytes
00101     static const int MAC_BYTES = 8;
00102     static const int IV_BYTES = 3;
00103     static const int OVERHEAD_BYTES = IV_BYTES + MAC_BYTES;
00104 
00105     // IV constants
00106     static const int IV_BITS = IV_BYTES * 8;
00107     static const u32 IV_MSB = (1 << IV_BITS);
00108     static const u32 IV_MASK = (IV_MSB - 1);
00109     static const u32 IV_FUZZ = 0xCA7DCA7D;
00110 
00111 protected:
00112     bool SetKey(int KeyBytes, Skein *key, bool is_initiator, const char *key_name);
00113 
00114     bool IsValidIV(u64 iv);
00115     void AcceptIV(u64 iv);
00116 
00117 public:
00118     // Generate a proof that the local host has the key
00119     bool GenerateProof(u8 *local_proof, int proof_bytes);
00120 
00121     // Validate a proof that the remote host has the key
00122     bool ValidateProof(const u8 *remote_proof, int proof_bytes);
00123 
00124 public:
00125     void AllowOutOfOrder(bool allowed = true) { _accept_out_of_order = allowed; }
00126 
00127 public:
00128     // Overhead is OVERHEAD_BYTES bytes at the end of the packet
00129     // Returns false if the message is invalid.  Invalid messages should just be ignored as if they were never received
00130     // buf_bytes: Number of bytes in the buffer, including the overhead
00131     // If Decrypt() returns true, buf_bytes is set to the size of the decrypted message
00132     bool Decrypt(u8 *buffer, u32 &buf_bytes);
00133 
00134     // Overhead is OVERHEAD_BYTES bytes at the end of the packet
00135     // buffer_bytes: Number of bytes in the buffer; will return false if buffer size too small
00136     // msg_bytes: Number of bytes in the message, excluding the overhead
00137     // If Encrypt() returns true, msg_bytes is set to the size of the encrypted message
00138     bool Encrypt(u8 *buffer, u32 buffer_bytes, u32 &msg_bytes);
00139 };
00140 
00141 
00142 
00143 } // namespace cat
00144 
00145 #endif // CAT_AUTHENTICATED_ENCRYPTION_HPP

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net