00001
00002
00003 #include "pch.h"
00004
00005 #ifndef CRYPTOPP_IMPORTS
00006
00007 #include "modes.h"
00008
00009 #ifndef NDEBUG
00010 #include "des.h"
00011 #endif
00012
00013 NAMESPACE_BEGIN(CryptoPP)
00014
00015 #ifndef NDEBUG
00016 void Modes_TestInstantiations()
00017 {
00018 CFB_Mode<DES>::Encryption m0;
00019 CFB_Mode<DES>::Decryption m1;
00020 OFB_Mode<DES>::Encryption m2;
00021 CTR_Mode<DES>::Encryption m3;
00022 ECB_Mode<DES>::Encryption m4;
00023 CBC_Mode<DES>::Encryption m5;
00024 }
00025 #endif
00026
00027 void CipherModeBase::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms)
00028 {
00029 UncheckedSetKey(params, key, (unsigned int)length, GetIVAndThrowIfInvalid(params));
00030 }
00031
00032 void CipherModeBase::GetNextIV(byte *IV)
00033 {
00034 if (!IsForwardTransformation())
00035 throw NotImplemented("CipherModeBase: GetNextIV() must be called on an encryption object");
00036
00037 m_cipher->ProcessBlock(m_register);
00038 memcpy(IV, m_register, BlockSize());
00039 }
00040
00041 void CTR_ModePolicy::SeekToIteration(lword iterationCount)
00042 {
00043 int carry=0;
00044 for (int i=BlockSize()-1; i>=0; i--)
00045 {
00046 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00047 m_counterArray[i] = (byte) sum;
00048 carry = sum >> 8;
00049 iterationCount >>= 8;
00050 }
00051 }
00052
00053 void CTR_ModePolicy::GetNextIV(byte *IV)
00054 {
00055 IncrementCounterByOne(IV, m_counterArray, BlockSize());
00056 }
00057
00058 inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, size_t n)
00059 {
00060 unsigned int s = BlockSize(), j = 0;
00061 for (unsigned int i=1; i<n; i++, j+=s)
00062 IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
00063 m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
00064 IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
00065 }
00066
00067 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00068 {
00069 unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
00070 if (maxBlocks == 1)
00071 {
00072 unsigned int sizeIncrement = BlockSize();
00073 while (iterationCount)
00074 {
00075 m_cipher->ProcessAndXorBlock(m_counterArray, input, output);
00076 IncrementCounterByOne(m_counterArray, sizeIncrement);
00077 output += sizeIncrement;
00078 input += sizeIncrement;
00079 iterationCount -= 1;
00080 }
00081 }
00082 else
00083 {
00084 unsigned int sizeIncrement = maxBlocks * BlockSize();
00085 while (iterationCount >= maxBlocks)
00086 {
00087 ProcessMultipleBlocks(output, input, maxBlocks);
00088 output += sizeIncrement;
00089 input += sizeIncrement;
00090 iterationCount -= maxBlocks;
00091 }
00092 if (iterationCount > 0)
00093 ProcessMultipleBlocks(output, input, iterationCount);
00094 }
00095 }
00096
00097 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00098 {
00099 unsigned int s = BlockSize();
00100 CopyOrZero(m_register, iv, s);
00101 m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
00102 CopyOrZero(m_counterArray, iv, s);
00103 }
00104
00105 void BlockOrientedCipherModeBase::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv)
00106 {
00107 m_cipher->SetKey(key, length, params);
00108 ResizeBuffers();
00109 if (IsResynchronizable())
00110 Resynchronize(iv);
00111 }
00112
00113 void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length)
00114 {
00115 unsigned int s = BlockSize();
00116 assert(length % s == 0);
00117 unsigned int alignment = m_cipher->BlockAlignment();
00118 bool inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment);
00119
00120 if (IsAlignedOn(outString, alignment))
00121 {
00122 if (inputAlignmentOk)
00123 ProcessBlocks(outString, inString, length / s);
00124 else
00125 {
00126 memcpy(outString, inString, length);
00127 ProcessBlocks(outString, outString, length / s);
00128 }
00129 }
00130 else
00131 {
00132 while (length)
00133 {
00134 if (inputAlignmentOk)
00135 ProcessBlocks(m_buffer, inString, 1);
00136 else
00137 {
00138 memcpy(m_buffer, inString, s);
00139 ProcessBlocks(m_buffer, m_buffer, 1);
00140 }
00141 memcpy(outString, m_buffer, s);
00142 inString += s;
00143 outString += s;
00144 length -= s;
00145 }
00146 }
00147 }
00148
00149 void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00150 {
00151 unsigned int blockSize = BlockSize();
00152 while (numberOfBlocks--)
00153 {
00154 xorbuf(m_register, inString, blockSize);
00155 m_cipher->ProcessBlock(m_register);
00156 memcpy(outString, m_register, blockSize);
00157 inString += blockSize;
00158 outString += blockSize;
00159 }
00160 }
00161
00162 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00163 {
00164 if (length <= BlockSize())
00165 {
00166 if (!m_stolenIV)
00167 throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00168
00169
00170 memcpy(outString, m_register, length);
00171 outString = m_stolenIV;
00172 }
00173 else
00174 {
00175
00176 xorbuf(m_register, inString, BlockSize());
00177 m_cipher->ProcessBlock(m_register);
00178 inString += BlockSize();
00179 length -= BlockSize();
00180 memcpy(outString+BlockSize(), m_register, length);
00181 }
00182
00183
00184 xorbuf(m_register, inString, length);
00185 m_cipher->ProcessBlock(m_register);
00186 memcpy(outString, m_register, BlockSize());
00187 }
00188
00189 void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00190 {
00191 unsigned int blockSize = BlockSize();
00192 while (numberOfBlocks--)
00193 {
00194 memcpy(m_temp, inString, blockSize);
00195 m_cipher->ProcessBlock(m_temp, outString);
00196 xorbuf(outString, m_register, blockSize);
00197 m_register.swap(m_temp);
00198 inString += blockSize;
00199 outString += blockSize;
00200 }
00201 }
00202
00203 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00204 {
00205 const byte *pn, *pn1;
00206 bool stealIV = length <= BlockSize();
00207
00208 if (stealIV)
00209 {
00210 pn = inString;
00211 pn1 = m_register;
00212 }
00213 else
00214 {
00215 pn = inString + BlockSize();
00216 pn1 = inString;
00217 length -= BlockSize();
00218 }
00219
00220
00221 memcpy(m_temp, pn1, BlockSize());
00222 m_cipher->ProcessBlock(m_temp);
00223 xorbuf(m_temp, pn, length);
00224
00225 if (stealIV)
00226 memcpy(outString, m_temp, length);
00227 else
00228 {
00229 memcpy(outString+BlockSize(), m_temp, length);
00230
00231 memcpy(m_temp, pn, length);
00232 m_cipher->ProcessBlock(m_temp);
00233 xorbuf(outString, m_temp, m_register, BlockSize());
00234 }
00235 }
00236
00237 NAMESPACE_END
00238
00239 #endif