2012-01-08 05:08:02 +01:00
|
|
|
/*
|
|
|
|
* This file is a part of Tito - a cryptography library
|
|
|
|
* and is distributed under the (new) BSD licence.
|
|
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2012, Tomasz Sowa
|
|
|
|
* 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 Tomasz Sowa nor the names of contributors to this
|
|
|
|
* project 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 OWNER 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 headerfile_tito_aes
|
|
|
|
#define headerfile_tito_aes
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
|
|
namespace Tito
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
class AES
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
typedef unsigned char uint8;
|
|
|
|
typedef unsigned short int uint16;
|
|
|
|
typedef unsigned int uint32;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 'state'
|
|
|
|
// 128 bits data block (16 bytes)
|
|
|
|
// this is input/output buffer for encoding/decoding
|
|
|
|
uint8 data[4][4];
|
|
|
|
|
|
|
|
// copying 16 bytes (128bits) buffer to/from 'data' table
|
|
|
|
void CopyToData(const uint8 * state);
|
2018-12-07 06:06:34 +01:00
|
|
|
void XorCopyToData(const AES::uint8 * state, const AES::uint8 * iv);
|
|
|
|
|
2012-01-08 05:08:02 +01:00
|
|
|
void CopyFromData(uint8 * state);
|
2018-12-07 06:06:34 +01:00
|
|
|
void XorCopyFromData(AES::uint8 * state, const AES::uint8 * iv);
|
|
|
|
|
2012-01-08 05:08:02 +01:00
|
|
|
void CopyFromData(std::vector<uint8> & out, bool clear = true);
|
|
|
|
|
|
|
|
// setting a new key
|
|
|
|
// key_length should be either: 16, 24 or 32
|
|
|
|
// if the key has incorrect length the method does nothing and returns false
|
|
|
|
bool Key(AES::uint8 * key_src, int key_length);
|
|
|
|
|
|
|
|
// encoding/decoding one 128 bits block
|
|
|
|
// you can set the value for encoding/decoding either by directly
|
|
|
|
// setting 'data' table or using CopyToData method
|
|
|
|
void EncodeData();
|
|
|
|
void DecodeData();
|
|
|
|
|
2018-12-07 06:06:34 +01:00
|
|
|
// encoding/decoding block of data - ECB (Electronic Codebook)
|
2012-01-08 05:08:02 +01:00
|
|
|
// the length should be multiplication of 16 (128bits)
|
|
|
|
// the method returns false if length is incorrect
|
|
|
|
bool Encode(uint8 * block, size_t len);
|
|
|
|
bool Decode(uint8 * block, size_t len);
|
|
|
|
|
2018-12-07 06:06:34 +01:00
|
|
|
|
|
|
|
// encoding/decoding block of data - CBC (Cipher Block Chaining)
|
|
|
|
// the length should be multiplication of 16 (128bits)
|
|
|
|
// the method returns false if length is incorrect
|
|
|
|
bool EncodeCBC(AES::uint8 * block, size_t len, const AES::uint8 * iv);
|
|
|
|
bool DecodeCBC(AES::uint8 * block, size_t len, const AES::uint8 * iv);
|
|
|
|
|
|
|
|
bool EncodeCBC_PKCS7(std::vector<uint8> & content, const AES::uint8 * iv);
|
|
|
|
bool DecodeCBC_PKCS7(std::vector<uint8> & content, const AES::uint8 * iv);
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-01-08 05:08:02 +01:00
|
|
|
// encoding/decoding block of data
|
|
|
|
// there is not any restrictions to the length
|
|
|
|
// we are using our own header in which we remember the length
|
|
|
|
// some control sums, how many padding bytes were used
|
|
|
|
// Encode returns always true
|
|
|
|
// Decode returns false is the control sums are different from original in the header
|
|
|
|
bool Encode(const uint8 * block, size_t len, const std::string & name, std::vector<uint8> & out);
|
|
|
|
bool Encode(const std::vector<uint8> & block, const std::string & name, std::vector<uint8> & out);
|
|
|
|
bool Decode(const uint8 * block, size_t len, std::string & name, std::vector<uint8> & out);
|
|
|
|
bool Decode(const std::vector<uint8> & block, std::string & name, std::vector<uint8> & out);
|
|
|
|
|
2018-12-07 06:06:34 +01:00
|
|
|
|
2012-01-08 05:08:02 +01:00
|
|
|
// printing 'data' tab
|
|
|
|
// for debug purposes
|
|
|
|
void PrintData();
|
|
|
|
void PrintKey(int xs);
|
|
|
|
void PrintKey2(int xs);
|
|
|
|
void PrintKey3(int xs);
|
|
|
|
bool CheckGFTables();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
|
|
// key (either 128 or 192 or 256 bits)
|
|
|
|
// and a space for key expansion
|
|
|
|
uint8 key[4][60];
|
|
|
|
|
|
|
|
// key length (in bytes)
|
|
|
|
// 16 for 128 bits
|
|
|
|
// 24 for 192 bits
|
|
|
|
// 32 for 256 bits
|
|
|
|
int key_len;
|
|
|
|
|
|
|
|
// key columns
|
|
|
|
// 4 for 128 bits key
|
|
|
|
// 6 for 192 bits key
|
|
|
|
// 8 for 256 bits key
|
|
|
|
int key_col;
|
|
|
|
|
|
|
|
// how many rounds should be performed
|
|
|
|
// 10 for 128 bits key
|
|
|
|
// 12 for 192 bits key
|
|
|
|
// 14 for 256 bits key
|
|
|
|
int round;
|
|
|
|
|
|
|
|
// sbox and inverse sbox tables (256 bytes each)
|
|
|
|
static uint8 sbox[16][16];
|
|
|
|
static uint8 invsbox[16][16];
|
|
|
|
|
|
|
|
// a table for mixcolumn state
|
|
|
|
static int mixcolumntab[4][4];
|
|
|
|
|
|
|
|
static uint8 Rcon[10];
|
|
|
|
|
|
|
|
|
|
|
|
static int invmixcolumntab[4][4];
|
|
|
|
|
|
|
|
static uint8 gf_mul9[16][16];
|
|
|
|
static uint8 gf_mul11[16][16];
|
|
|
|
static uint8 gf_mul13[16][16];
|
|
|
|
static uint8 gf_mul14[16][16];
|
|
|
|
|
|
|
|
// returning a coresponding value from sbox table
|
|
|
|
uint8 SubBytes(AES::uint8 v);
|
|
|
|
|
|
|
|
// making the SubBytes algorithm on all items in 'data' table
|
|
|
|
void SubBytes();
|
|
|
|
|
|
|
|
// performing shift rows by 1 item
|
|
|
|
void ShiftRows1(AES::uint8 tab[4]);
|
|
|
|
|
|
|
|
// performing shift rows by 2 items
|
|
|
|
void ShiftRows2(AES::uint8 tab[4]);
|
|
|
|
|
|
|
|
// performing shift rows by 3 item
|
|
|
|
void ShiftRows3(AES::uint8 tab[4]);
|
|
|
|
|
|
|
|
// performing shift rows on 'data' table
|
|
|
|
void ShiftRows();
|
|
|
|
|
|
|
|
|
|
|
|
uint8 MixColumns2(uint8 v);
|
|
|
|
uint8 MixColumns3(uint8 v);
|
|
|
|
uint8 MixColumns(int type, uint8 value);
|
|
|
|
void MixColumns();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void RotKey(int i);
|
|
|
|
void SubWordKey(int i);
|
|
|
|
void KeyExpansion();
|
|
|
|
|
|
|
|
void AddRoundKey(int xs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* inverse */
|
|
|
|
|
|
|
|
void InvShiftRows1(uint8 tab[4]);
|
|
|
|
void InvShiftRows2(uint8 tab[4]);
|
|
|
|
void InvShiftRows3(uint8 tab[4]);
|
|
|
|
void InvShiftRows();
|
|
|
|
|
|
|
|
uint8 InvSubBytes(uint8 v);
|
|
|
|
void InvSubBytes();
|
|
|
|
void InvMixColumns();
|
|
|
|
|
|
|
|
uint8 InvMixColumns(uint8 gf_mul[16][16], uint8 v);
|
|
|
|
uint8 InvMixColumns(int type, uint8 value);
|
|
|
|
|
|
|
|
|
|
|
|
/* for debug */
|
|
|
|
|
|
|
|
uint8 GaloisMultiply(uint8 a, uint8 b);
|
|
|
|
bool CheckGFTable(int value, uint8 gf_mul[16][16]);
|
|
|
|
|
|
|
|
|
|
|
|
struct TiHeader
|
|
|
|
{
|
|
|
|
AES::uint16 signature;
|
|
|
|
AES::uint16 pad1;
|
|
|
|
AES::uint16 pad2;
|
|
|
|
AES::uint32 checksum_before;
|
|
|
|
AES::uint32 checksum_after;
|
|
|
|
AES::uint32 name_len;
|
|
|
|
size_t all_len;
|
|
|
|
};
|
|
|
|
|
|
|
|
void IntToBuf(uint8 * buf, uint16 value);
|
|
|
|
void IntToBuf(uint8 * buf, uint32 value);
|
2018-12-07 06:06:34 +01:00
|
|
|
void CreateHeader(TiHeader & header, const uint8 * block, size_t len, const std::string & name, bool use_rand_first_padding = true);
|
2012-01-08 05:08:02 +01:00
|
|
|
void PutHeader(const TiHeader & header, std::vector<uint8> & out);
|
|
|
|
void PutChecksumAfter(std::vector<AES::uint8> & out);
|
|
|
|
uint32 Checksum(const uint8 * block, size_t len);
|
|
|
|
void EncodePad(int & y, int & x, uint16 pad, std::vector<uint8> & out);
|
|
|
|
void EncodeName(int & y, int & x, const std::string & name, std::vector<uint8> & out);
|
|
|
|
void EncodeData(int & y, int & x, const uint8 * block, size_t len, std::vector<uint8> & out);
|
|
|
|
|
|
|
|
void ReadHeader(TiHeader & header, const uint8 * block);
|
|
|
|
void DecodePad(int & y, int & x, const uint8 * & block, size_t & len, uint16 pad);
|
|
|
|
void DecodeName(int & y, int & x, const uint8 * & block, size_t & len, uint32 name_len, std::string & name);
|
|
|
|
void DecodeData(int & y, int & x, const uint8 * & block, size_t & len, size_t data_len, std::vector<uint8> & out);
|
|
|
|
|
|
|
|
bool CheckSignatureAndChecksumAfter(const TiHeader & header, const uint8 * block, size_t len);
|
|
|
|
bool CheckChecksumBefore(const TiHeader & header, std::vector<uint8> & out);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Tito
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|