From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- cryptopp/crypto/modes.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 cryptopp/crypto/modes.cpp (limited to 'cryptopp/crypto/modes.cpp') diff --git a/cryptopp/crypto/modes.cpp b/cryptopp/crypto/modes.cpp new file mode 100644 index 0000000..21bcc4c --- /dev/null +++ b/cryptopp/crypto/modes.cpp @@ -0,0 +1,209 @@ +// modes.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "modes.h" + +#ifndef NDEBUG +#include "des.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#ifndef NDEBUG +void Modes_TestInstantiations() +{ + CFB_Mode::Encryption m0; + CFB_Mode::Decryption m1; + OFB_Mode::Encryption m2; + CTR_Mode::Encryption m3; + ECB_Mode::Encryption m4; + CBC_Mode::Encryption m5; +} +#endif + +void CTR_ModePolicy::SeekToIteration(lword iterationCount) +{ + int carry=0; + for (int i=BlockSize()-1; i>=0; i--) + { + unsigned int sum = m_register[i] + byte(iterationCount) + carry; + m_counterArray[i] = (byte) sum; + carry = sum >> 8; + iterationCount >>= 8; + } +} + +inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, size_t n) +{ + unsigned int s = BlockSize(), j = 0; + for (unsigned int i=1; iProcessAndXorMultipleBlocks(m_counterArray, input, output, n); + IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s); +} + +void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + assert(m_cipher->IsForwardTransformation()); // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt + unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks(); + if (maxBlocks == 1) + { + unsigned int sizeIncrement = BlockSize(); + while (iterationCount) + { + m_cipher->ProcessAndXorBlock(m_counterArray, input, output); + IncrementCounterByOne(m_counterArray, sizeIncrement); + output += sizeIncrement; + input += sizeIncrement; + iterationCount -= 1; + } + } + else + { + unsigned int sizeIncrement = maxBlocks * BlockSize(); + while (iterationCount >= maxBlocks) + { + ProcessMultipleBlocks(output, input, maxBlocks); + output += sizeIncrement; + input += sizeIncrement; + iterationCount -= maxBlocks; + } + if (iterationCount > 0) + ProcessMultipleBlocks(output, input, iterationCount); + } +} + +void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv) +{ + unsigned int s = BlockSize(); + CopyOrZero(m_register, iv, s); + m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks()); + CopyOrZero(m_counterArray, iv, s); +} + +void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + m_cipher->SetKey(key, length, params); + ResizeBuffers(); + if (IsResynchronizable()) + Resynchronize(GetIVAndThrowIfInvalid(params)); +} + +void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (!length) + return; + + unsigned int s = BlockSize(); + assert(length % s == 0); + + if (!RequireAlignedInput() || IsAlignedOn(inString, m_cipher->BlockAlignment())) + ProcessBlocks(outString, inString, length / s); + else + { + do + { + memcpy(m_buffer, inString, s); + ProcessBlocks(outString, m_buffer, 1); + inString += s; + outString += s; + length -= s; + } while (length > 0); + } +} + +void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks) +{ + unsigned int blockSize = BlockSize(); + xorbuf(m_register, inString, blockSize); + while (--numberOfBlocks) + { + m_cipher->ProcessBlock(m_register, outString); + inString += blockSize; + xorbuf(m_register, inString, outString, blockSize); + outString += blockSize; + } + m_cipher->ProcessBlock(m_register); + memcpy(outString, m_register, blockSize); +} + +void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + if (length <= BlockSize()) + { + if (!m_stolenIV) + throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing"); + + // steal from IV + memcpy(outString, m_register, length); + outString = m_stolenIV; + } + else + { + // steal from next to last block + xorbuf(m_register, inString, BlockSize()); + m_cipher->ProcessBlock(m_register); + inString += BlockSize(); + length -= BlockSize(); + memcpy(outString+BlockSize(), m_register, length); + } + + // output last full ciphertext block + xorbuf(m_register, inString, length); + m_cipher->ProcessBlock(m_register); + memcpy(outString, m_register, BlockSize()); +} + +void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks) +{ + unsigned int blockSize = BlockSize(); + do + { + memcpy(m_temp, inString, blockSize); // make copy in case we're doing in place decryption + m_cipher->ProcessAndXorBlock(m_temp, m_register, outString); + m_register.swap(m_temp); + inString += blockSize; + outString += blockSize; + } while (--numberOfBlocks); +} + +void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + const byte *pn, *pn1; + bool stealIV = length <= BlockSize(); + + if (stealIV) + { + pn = inString; + pn1 = m_register; + } + else + { + pn = inString + BlockSize(); + pn1 = inString; + length -= BlockSize(); + } + + // decrypt last partial plaintext block + memcpy(m_temp, pn1, BlockSize()); + m_cipher->ProcessBlock(m_temp); + xorbuf(m_temp, pn, length); + + if (stealIV) + memcpy(outString, m_temp, length); + else + { + memcpy(outString+BlockSize(), m_temp, length); + // decrypt next to last plaintext block + memcpy(m_temp, pn, length); + m_cipher->ProcessBlock(m_temp); + xorbuf(outString, m_temp, m_register, BlockSize()); + } +} + +NAMESPACE_END + +#endif -- cgit v1.2.3