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