00001
00002
00003
00004
00005
00006
00007
00008 #include "DataBlockEncryptor.h"
00009 #include "CheckSum.h"
00010 #include "GetTime.h"
00011 #include "Rand.h"
00012 #include "RakAssert.h"
00013 #include <string.h>
00014 #include "Rijndael.h"
00015
00016
00017 DataBlockEncryptor::DataBlockEncryptor()
00018 {
00019 keySet = false;
00020 }
00021
00022 DataBlockEncryptor::~DataBlockEncryptor()
00023 {}
00024
00025 bool DataBlockEncryptor::IsKeySet( void ) const
00026 {
00027 return keySet;
00028 }
00029
00030 void DataBlockEncryptor::SetKey( const unsigned char key[ 16 ] )
00031 {
00032 keySet = true;
00033
00034 makeKey(&keyEncrypt, DIR_ENCRYPT, 16, (char*)key);
00035 makeKey(&keyDecrypt, DIR_DECRYPT, 16, (char*)key);
00036 cipherInit(&cipherInst, MODE_ECB, 0);
00037 }
00038
00039 void DataBlockEncryptor::UnsetKey( void )
00040 {
00041 keySet = false;
00042 }
00043
00044 void DataBlockEncryptor::Encrypt( unsigned char *input, unsigned int inputLength, unsigned char *output, unsigned int *outputLength, RakNetRandom *rnr )
00045 {
00046 unsigned index, byteIndex, lastBlock;
00047 unsigned int checkSum;
00048 unsigned char paddingBytes;
00049 unsigned char encodedPad;
00050 unsigned char randomChar;
00051 CheckSum checkSumCalculator;
00052
00053 #ifdef _DEBUG
00054
00055 RakAssert( keySet );
00056 #endif
00057
00058 RakAssert( input && inputLength );
00059
00060
00061
00062 randomChar = (unsigned char) rnr->RandomMT();
00063
00064
00065
00066
00067 paddingBytes = (unsigned char) ( 16 - ( ( ( inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) - 1 ) % 16 ) + 1 ) );
00068
00069
00070 encodedPad = (unsigned char) rnr->RandomMT();
00071 encodedPad <<= 4;
00072 encodedPad |= paddingBytes;
00073
00074 *outputLength = inputLength + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes;
00075
00076
00077
00078 if ( input == output )
00079 memmove( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength );
00080 else
00081 memcpy( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes, input, inputLength );
00082
00083
00084 memcpy( output + sizeof( checkSum ), ( char* ) & randomChar, sizeof( randomChar ) );
00085
00086
00087 memcpy( output + sizeof( checkSum ) + sizeof( randomChar ), ( char* ) & encodedPad, sizeof( encodedPad ) );
00088
00089
00090 for ( index = 0; index < paddingBytes; index++ )
00091 *( output + sizeof( checkSum ) + sizeof( randomChar ) + sizeof( encodedPad ) + index ) = (unsigned char) rnr->RandomMT();
00092
00093
00094 checkSumCalculator.Add( output + sizeof( checkSum ), inputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes );
00095
00096 checkSum = checkSumCalculator.Get();
00097
00098
00099 #ifdef HOST_ENDIAN_IS_BIG
00100 output[0] = checkSum&0xFF;
00101 output[1] = (checkSum>>8)&0xFF;
00102 output[2] = (checkSum>>16)&0xFF;
00103 output[3] = (checkSum>>24)&0xFF;
00104 #else
00105 memcpy( output, ( char* ) & checkSum, sizeof( checkSum ) );
00106 #endif
00107
00108
00109
00110 blockEncrypt(&cipherInst, &keyEncrypt, output, 16, output);
00111
00112 lastBlock = 0;
00113
00114
00115 for ( index = *outputLength - 16; index >= 16; index -= 16 )
00116 {
00117 for ( byteIndex = 0; byteIndex < 16; byteIndex++ )
00118 output[ index + byteIndex ] ^= output[ lastBlock + byteIndex ];
00119
00120
00121 blockEncrypt(&cipherInst, &keyEncrypt, output+index, 16, output+index);
00122
00123 lastBlock = index;
00124 }
00125 }
00126
00127 bool DataBlockEncryptor::Decrypt( unsigned char *input, unsigned int inputLength, unsigned char *output, unsigned int *outputLength )
00128 {
00129 unsigned index, byteIndex;
00130 unsigned int checkSum;
00131 unsigned char paddingBytes;
00132 unsigned char encodedPad;
00133 unsigned char randomChar;
00134 CheckSum checkSumCalculator;
00135 #ifdef _DEBUG
00136
00137 RakAssert( keySet );
00138 #endif
00139
00140 if ( input == 0 || inputLength < 16 || ( inputLength % 16 ) != 0 )
00141 {
00142 return false;
00143 }
00144
00145
00146 for ( index = 16; index <= inputLength - 16;index += 16 )
00147 {
00148
00149 blockDecrypt(&cipherInst, &keyDecrypt, input + index, 16, output + index);
00150
00151 for ( byteIndex = 0; byteIndex < 16; byteIndex++ )
00152 {
00153 if ( index + 16 == ( unsigned ) inputLength )
00154 output[ index + byteIndex ] ^= input[ byteIndex ];
00155 else
00156 output[ index + byteIndex ] ^= input[ index + 16 + byteIndex ];
00157 }
00158
00159
00160 };
00161
00162
00163
00164 blockDecrypt(&cipherInst, &keyDecrypt, input, 16, output);
00165
00166
00167 #ifdef HOST_ENDIAN_IS_BIG
00168 checkSum = (unsigned int)output[0] | (unsigned int)(output[1]<<8) |
00169 (unsigned int)(output[2]<<16)|(unsigned int)(output[3]<<24);
00170 #else
00171 memcpy( ( char* ) & checkSum, output, sizeof( checkSum ) );
00172 #endif
00173
00174
00175 memcpy( ( char* ) & encodedPad, output + sizeof( randomChar ) + sizeof( checkSum ), sizeof( encodedPad ) );
00176
00177
00178 paddingBytes = encodedPad & 0x0F;
00179
00180
00181
00182 *outputLength = inputLength - sizeof( randomChar ) - sizeof( checkSum ) - sizeof( encodedPad ) - paddingBytes;
00183
00184
00185 checkSumCalculator.Add( output + sizeof( checkSum ), *outputLength + sizeof( randomChar ) + sizeof( encodedPad ) + paddingBytes );
00186
00187 if ( checkSum != checkSumCalculator.Get() )
00188 return false;
00189
00190
00191
00192 memmove( output, output + sizeof( randomChar ) + sizeof( checkSum ) + sizeof( encodedPad ) + paddingBytes, *outputLength );
00193
00194
00195
00196 return true;
00197 }