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, unsigned int length, const NameValuePairs ¶ms)
00028 {
00029 UncheckedSetKey(params, key, length);
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 CipherModeBase::SetIV(const byte *iv)
00042 {
00043 if (iv)
00044 Resynchronize(iv);
00045 else if (IsResynchronizable())
00046 {
00047 if (!CanUseStructuredIVs())
00048 throw InvalidArgument("CipherModeBase: this cipher mode cannot use a null IV");
00049
00050
00051 SecByteBlock iv(BlockSize());
00052 memset(iv, 0, iv.size());
00053 Resynchronize(iv);
00054 }
00055 }
00056
00057 void CTR_ModePolicy::GetNextIV(byte *IV)
00058 {
00059 IncrementCounterByOne(IV, m_counterArray, BlockSize());
00060 }
00061
00062 void CTR_ModePolicy::SeekToIteration(dword iterationCount)
00063 {
00064 int carry=0;
00065 for (int i=BlockSize()-1; i>=0 && (iterationCount || carry); i--)
00066 {
00067 unsigned int sum = m_counterArray[i] + byte(iterationCount) + carry;
00068 m_counterArray[i] = (byte) sum;
00069 carry = sum >> 8;
00070 iterationCount >>= 8;
00071 }
00072 }
00073
00074 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount)
00075 {
00076 unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
00077 unsigned int sizeIncrement = maxBlocks * m_cipher->BlockSize();
00078 while (iterationCount >= maxBlocks)
00079 {
00080 ProcessMultipleBlocks(output, input, maxBlocks);
00081 output += sizeIncrement;
00082 input += sizeIncrement;
00083 iterationCount -= maxBlocks;
00084 }
00085 if (iterationCount > 0)
00086 ProcessMultipleBlocks(output, input, iterationCount);
00087 }
00088 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00089 {
00090 unsigned int s = BlockSize();
00091 memcpy(m_register, iv, s);
00092 m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
00093 memcpy(m_counterArray, iv, s);
00094 }
00095
00096 void BlockOrientedCipherModeBase::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
00097 {
00098 m_cipher->SetKey(key, length, params);
00099 ResizeBuffers();
00100 const byte *iv = params.GetValueWithDefault(Name::IV(), (const byte *)NULL);
00101 SetIV(iv);
00102 }
00103
00104 void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, unsigned int length)
00105 {
00106 unsigned int s = BlockSize();
00107 assert(length % s == 0);
00108 unsigned int alignment = m_cipher->BlockAlignment();
00109 bool requireAlignedInput = RequireAlignedInput();
00110
00111 if (IsAlignedOn(outString, alignment))
00112 {
00113 if (!requireAlignedInput || IsAlignedOn(inString, alignment))
00114 ProcessBlocks(outString, inString, length / s);
00115 else
00116 {
00117 memcpy(outString, inString, length);
00118 ProcessBlocks(outString, outString, length / s);
00119 }
00120 }
00121 else
00122 {
00123 while (length)
00124 {
00125 if (!requireAlignedInput || IsAlignedOn(inString, alignment))
00126 ProcessBlocks(m_buffer, inString, 1);
00127 else
00128 {
00129 memcpy(m_buffer, inString, s);
00130 ProcessBlocks(m_buffer, m_buffer, 1);
00131 }
00132 memcpy(outString, m_buffer, s);
00133 length -= s;
00134 }
00135 }
00136 }
00137
00138 void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
00139 {
00140 unsigned int blockSize = BlockSize();
00141 while (numberOfBlocks--)
00142 {
00143 xorbuf(m_register, inString, blockSize);
00144 m_cipher->ProcessBlock(m_register);
00145 memcpy(outString, m_register, blockSize);
00146 inString += blockSize;
00147 outString += blockSize;
00148 }
00149 }
00150
00151 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
00152 {
00153 if (length <= BlockSize())
00154 {
00155 if (!m_stolenIV)
00156 throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00157
00158
00159 memcpy(outString, m_register, length);
00160 outString = m_stolenIV;
00161 }
00162 else
00163 {
00164
00165 xorbuf(m_register, inString, BlockSize());
00166 m_cipher->ProcessBlock(m_register);
00167 inString += BlockSize();
00168 length -= BlockSize();
00169 memcpy(outString+BlockSize(), m_register, length);
00170 }
00171
00172
00173 xorbuf(m_register, inString, length);
00174 m_cipher->ProcessBlock(m_register);
00175 memcpy(outString, m_register, BlockSize());
00176 }
00177
00178 void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
00179 {
00180 unsigned int blockSize = BlockSize();
00181 while (numberOfBlocks--)
00182 {
00183 memcpy(m_temp, inString, blockSize);
00184 m_cipher->ProcessBlock(m_temp, outString);
00185 xorbuf(outString, m_register, blockSize);
00186 m_register.swap(m_temp);
00187 inString += blockSize;
00188 outString += blockSize;
00189 }
00190 }
00191
00192 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
00193 {
00194 const byte *pn, *pn1;
00195 bool stealIV = length <= BlockSize();
00196
00197 if (stealIV)
00198 {
00199 pn = inString;
00200 pn1 = m_register;
00201 }
00202 else
00203 {
00204 pn = inString + BlockSize();
00205 pn1 = inString;
00206 length -= BlockSize();
00207 }
00208
00209
00210 memcpy(m_temp, pn1, BlockSize());
00211 m_cipher->ProcessBlock(m_temp);
00212 xorbuf(m_temp, pn, length);
00213
00214 if (stealIV)
00215 memcpy(outString, m_temp, length);
00216 else
00217 {
00218 memcpy(outString+BlockSize(), m_temp, length);
00219
00220 memcpy(m_temp, pn, length);
00221 m_cipher->ProcessBlock(m_temp);
00222 xorbuf(outString, m_temp, m_register, BlockSize());
00223 }
00224 }
00225
00226 NAMESPACE_END
00227
00228 #endif