Crypto++
|
00001 // strciphr.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 00005 #ifndef CRYPTOPP_IMPORTS 00006 00007 #include "strciphr.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 template <class S> 00012 void AdditiveCipherTemplate<S>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) 00013 { 00014 PolicyInterface &policy = this->AccessPolicy(); 00015 policy.CipherSetKey(params, key, length); 00016 m_leftOver = 0; 00017 unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy)); 00018 m_buffer.New(bufferByteSize); 00019 00020 if (this->IsResynchronizable()) 00021 { 00022 size_t ivLength; 00023 const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); 00024 policy.CipherResynchronize(m_buffer, iv, ivLength); 00025 } 00026 } 00027 00028 template <class S> 00029 void AdditiveCipherTemplate<S>::GenerateBlock(byte *outString, size_t length) 00030 { 00031 if (m_leftOver > 0) 00032 { 00033 size_t len = STDMIN(m_leftOver, length); 00034 memcpy(outString, KeystreamBufferEnd()-m_leftOver, len); 00035 length -= len; 00036 m_leftOver -= len; 00037 outString += len; 00038 00039 if (!length) 00040 return; 00041 } 00042 assert(m_leftOver == 0); 00043 00044 PolicyInterface &policy = this->AccessPolicy(); 00045 unsigned int bytesPerIteration = policy.GetBytesPerIteration(); 00046 00047 if (length >= bytesPerIteration) 00048 { 00049 size_t iterations = length / bytesPerIteration; 00050 policy.WriteKeystream(outString, iterations); 00051 outString += iterations * bytesPerIteration; 00052 length -= iterations * bytesPerIteration; 00053 } 00054 00055 if (length > 0) 00056 { 00057 size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); 00058 size_t bufferIterations = bufferByteSize / bytesPerIteration; 00059 00060 policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); 00061 memcpy(outString, KeystreamBufferEnd()-bufferByteSize, length); 00062 m_leftOver = bufferByteSize - length; 00063 } 00064 } 00065 00066 template <class S> 00067 void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inString, size_t length) 00068 { 00069 if (m_leftOver > 0) 00070 { 00071 size_t len = STDMIN(m_leftOver, length); 00072 xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len); 00073 length -= len; 00074 m_leftOver -= len; 00075 inString += len; 00076 outString += len; 00077 00078 if (!length) 00079 return; 00080 } 00081 assert(m_leftOver == 0); 00082 00083 PolicyInterface &policy = this->AccessPolicy(); 00084 unsigned int bytesPerIteration = policy.GetBytesPerIteration(); 00085 00086 if (policy.CanOperateKeystream() && length >= bytesPerIteration) 00087 { 00088 size_t iterations = length / bytesPerIteration; 00089 unsigned int alignment = policy.GetAlignment(); 00090 KeystreamOperation operation = KeystreamOperation((IsAlignedOn(inString, alignment) * 2) | (int)IsAlignedOn(outString, alignment)); 00091 00092 policy.OperateKeystream(operation, outString, inString, iterations); 00093 00094 inString += iterations * bytesPerIteration; 00095 outString += iterations * bytesPerIteration; 00096 length -= iterations * bytesPerIteration; 00097 00098 if (!length) 00099 return; 00100 } 00101 00102 size_t bufferByteSize = m_buffer.size(); 00103 size_t bufferIterations = bufferByteSize / bytesPerIteration; 00104 00105 while (length >= bufferByteSize) 00106 { 00107 policy.WriteKeystream(m_buffer, bufferIterations); 00108 xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); 00109 length -= bufferByteSize; 00110 inString += bufferByteSize; 00111 outString += bufferByteSize; 00112 } 00113 00114 if (length > 0) 00115 { 00116 bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); 00117 bufferIterations = bufferByteSize / bytesPerIteration; 00118 00119 policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); 00120 xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length); 00121 m_leftOver = bufferByteSize - length; 00122 } 00123 } 00124 00125 template <class S> 00126 void AdditiveCipherTemplate<S>::Resynchronize(const byte *iv, int length) 00127 { 00128 PolicyInterface &policy = this->AccessPolicy(); 00129 m_leftOver = 0; 00130 m_buffer.New(GetBufferByteSize(policy)); 00131 policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length)); 00132 } 00133 00134 template <class BASE> 00135 void AdditiveCipherTemplate<BASE>::Seek(lword position) 00136 { 00137 PolicyInterface &policy = this->AccessPolicy(); 00138 unsigned int bytesPerIteration = policy.GetBytesPerIteration(); 00139 00140 policy.SeekToIteration(position / bytesPerIteration); 00141 position %= bytesPerIteration; 00142 00143 if (position > 0) 00144 { 00145 policy.WriteKeystream(KeystreamBufferEnd()-bytesPerIteration, 1); 00146 m_leftOver = bytesPerIteration - (unsigned int)position; 00147 } 00148 else 00149 m_leftOver = 0; 00150 } 00151 00152 template <class BASE> 00153 void CFB_CipherTemplate<BASE>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) 00154 { 00155 PolicyInterface &policy = this->AccessPolicy(); 00156 policy.CipherSetKey(params, key, length); 00157 00158 if (this->IsResynchronizable()) 00159 { 00160 size_t ivLength; 00161 const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); 00162 policy.CipherResynchronize(iv, ivLength); 00163 } 00164 00165 m_leftOver = policy.GetBytesPerIteration(); 00166 } 00167 00168 template <class BASE> 00169 void CFB_CipherTemplate<BASE>::Resynchronize(const byte *iv, int length) 00170 { 00171 PolicyInterface &policy = this->AccessPolicy(); 00172 policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length)); 00173 m_leftOver = policy.GetBytesPerIteration(); 00174 } 00175 00176 template <class BASE> 00177 void CFB_CipherTemplate<BASE>::ProcessData(byte *outString, const byte *inString, size_t length) 00178 { 00179 assert(length % this->MandatoryBlockSize() == 0); 00180 00181 PolicyInterface &policy = this->AccessPolicy(); 00182 unsigned int bytesPerIteration = policy.GetBytesPerIteration(); 00183 unsigned int alignment = policy.GetAlignment(); 00184 byte *reg = policy.GetRegisterBegin(); 00185 00186 if (m_leftOver) 00187 { 00188 size_t len = STDMIN(m_leftOver, length); 00189 CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len); 00190 m_leftOver -= len; 00191 length -= len; 00192 inString += len; 00193 outString += len; 00194 } 00195 00196 if (!length) 00197 return; 00198 00199 assert(m_leftOver == 0); 00200 00201 if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) 00202 { 00203 if (IsAlignedOn(inString, alignment)) 00204 policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration); 00205 else 00206 { 00207 memcpy(outString, inString, length); 00208 policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration); 00209 } 00210 inString += length - length % bytesPerIteration; 00211 outString += length - length % bytesPerIteration; 00212 length %= bytesPerIteration; 00213 } 00214 00215 while (length >= bytesPerIteration) 00216 { 00217 policy.TransformRegister(); 00218 CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); 00219 length -= bytesPerIteration; 00220 inString += bytesPerIteration; 00221 outString += bytesPerIteration; 00222 } 00223 00224 if (length > 0) 00225 { 00226 policy.TransformRegister(); 00227 CombineMessageAndShiftRegister(outString, reg, inString, length); 00228 m_leftOver = bytesPerIteration - length; 00229 } 00230 } 00231 00232 template <class BASE> 00233 void CFB_EncryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) 00234 { 00235 xorbuf(reg, message, length); 00236 memcpy(output, reg, length); 00237 } 00238 00239 template <class BASE> 00240 void CFB_DecryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) 00241 { 00242 for (unsigned int i=0; i<length; i++) 00243 { 00244 byte b = message[i]; 00245 output[i] = reg[i] ^ b; 00246 reg[i] = b; 00247 } 00248 } 00249 00250 NAMESPACE_END 00251 00252 #endif