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