From b21162cf8e06f40baa1f58be6a8c17435cebc34d Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 4 Oct 2002 17:31:41 +0000 Subject: Initial revision git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@2 57ff6487-cd31-0410-9ec3-f628ee90f5f0 --- strciphr.h | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 strciphr.h (limited to 'strciphr.h') diff --git a/strciphr.h b/strciphr.h new file mode 100644 index 0000000..12fb95e --- /dev/null +++ b/strciphr.h @@ -0,0 +1,287 @@ +/*! \file + This file contains helper classes for implementing stream ciphers. + + All this infrastructure may look very complex compared to what's in Crypto++ 4.x, + but stream ciphers implementations now support a lot of new functionality, + including better performance (minimizing copying), resetting of keys and IVs, and methods to + query which features are supported by a cipher. + + Here's an explanation of these classes. The word "policy" is used here to mean a class with a + set of methods that must be implemented by individual stream cipher implementations. + This is usually much simpler than the full stream cipher API, which is implemented by + either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an + implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface + (since it's an additive cipher, i.e., it xors a keystream into the plaintext). + See this line in seal.h: + + typedef SymmetricCipherFinalTemplate, AdditiveCipherTemplate<> > > Encryption; + + AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need + to take a policy class as a template parameter (although this is allowed), so that + their code is not duplicated for each new cipher. Instead they each + get a reference to an abstract policy interface by calling AccessPolicy() on itself, so + AccessPolicy() must be overriden to return the actual policy reference. This is done + by the ConceretePolicyHolder class. Finally, SymmetricCipherFinalTemplate implements the constructors and + other functions that must be implemented by the most derived class. +*/ + +#ifndef CRYPTOPP_STRCIPHR_H +#define CRYPTOPP_STRCIPHR_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +template +class AbstractPolicyHolder : public BASE +{ +protected: + typedef POLICY_INTERFACE PolicyInterface; + + virtual const POLICY_INTERFACE & GetPolicy() const =0; + virtual POLICY_INTERFACE & AccessPolicy() =0; +}; + +template +class ConcretePolicyHolder : public BASE, protected POLICY +{ +protected: + const POLICY_INTERFACE & GetPolicy() const {return *this;} + POLICY_INTERFACE & AccessPolicy() {return *this;} +}; + +enum KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE}; + +struct AdditiveCipherAbstractPolicy +{ + virtual unsigned int GetAlignment() const =0; + virtual unsigned int GetBytesPerIteration() const =0; + virtual unsigned int GetIterationsToBuffer() const =0; + virtual void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount) =0; + virtual bool CanOperateKeystream() const {return false;} + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) {assert(false);} + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0; + virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");} + virtual bool IsRandomAccess() const =0; + virtual void SeekToIteration(dword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");} +}; + +template +struct AdditiveCipherConcretePolicy : public BASE +{ + typedef WT WordType; + + unsigned int GetAlignment() const {return sizeof(WordType);} + unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} + unsigned int GetIterationsToBuffer() const {return X;} + void WriteKeystream(byte *buffer, unsigned int iterationCount) + {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);} + bool CanOperateKeystream() const {return true;} + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) =0; + + template + struct KeystreamOutput + { + KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input) + : m_operation(operation), m_output(output), m_input(input) {} + + inline KeystreamOutput & operator()(WordType keystreamWord) + { + assert(IsAligned(m_input)); + assert(IsAligned(m_output)); + + if (!NativeByteOrderIs(B::ToEnum())) + keystreamWord = ByteReverse(keystreamWord); + + if (m_operation == WRITE_KEYSTREAM) + *(WordType*)m_output = keystreamWord; + else if (m_operation == XOR_KEYSTREAM) + { + *(WordType*)m_output = keystreamWord ^ *(WordType*)m_input; + m_input += sizeof(WordType); + } + else if (m_operation == XOR_KEYSTREAM_INPLACE) + *(WordType*)m_output ^= keystreamWord; + + m_output += sizeof(WordType); + + return *this; + } + + KeystreamOperation m_operation; + byte *m_output; + const byte *m_input; + }; +}; + +template > > +class AdditiveCipherTemplate : public BASE +{ +public: + byte GenerateByte(); + void ProcessData(byte *outString, const byte *inString, unsigned int length); + void Resynchronize(const byte *iv); + unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();} + unsigned int GetOptimalNextBlockSize() const {return m_leftOver;} + unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();} + bool IsSelfInverting() const {return true;} + bool IsForwardTransformation() const {return true;} + bool IsRandomAccess() const {return GetPolicy().IsRandomAccess();} + void Seek(dword position); + +protected: + typedef typename BASE::PolicyInterface PolicyInterface; + + void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length); + + unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} + + inline byte * KeystreamBufferBegin() {return m_buffer.data();} + inline byte * KeystreamBufferEnd() {return (m_buffer.data() + m_buffer.size());} + + SecByteBlock m_buffer; + unsigned int m_leftOver; +}; + +struct CFB_CipherAbstractPolicy +{ + virtual unsigned int GetAlignment() const =0; + virtual unsigned int GetBytesPerIteration() const =0; + virtual byte * GetRegisterBegin() =0; + virtual void TransformRegister() =0; + virtual bool CanIterate() const {return false;} + virtual void Iterate(byte *output, const byte *input, CipherDir dir, unsigned int iterationCount) {assert(false);} + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0; + virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");} +}; + +template +struct CFB_CipherConcretePolicy : public BASE +{ + typedef WT WordType; + + unsigned int GetAlignment() const {return sizeof(WordType);} + unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} + bool CanIterate() const {return true;} + void TransformRegister() {Iterate(NULL, NULL, ENCRYPTION, 1);} + + template + struct RegisterOutput + { + RegisterOutput(byte *output, const byte *input, CipherDir dir) + : m_output(output), m_input(input), m_dir(dir) {} + + inline RegisterOutput& operator()(WordType ®isterWord) + { + assert(IsAligned(m_output)); + assert(IsAligned(m_input)); + + if (!NativeByteOrderIs(B::ToEnum())) + registerWord = ByteReverse(registerWord); + + if (m_dir == ENCRYPTION) + { + WordType ct = *(const WordType *)m_input ^ registerWord; + registerWord = ct; + *(WordType*)m_output = ct; + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + else + { + WordType ct = *(const WordType *)m_input; + *(WordType*)m_output = registerWord ^ ct; + registerWord = ct; + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + + // registerWord is left unreversed so it can be xor-ed with further input + + return *this; + } + + byte *m_output; + const byte *m_input; + CipherDir m_dir; + }; +}; + +template +class CFB_CipherTemplate : public BASE +{ +public: + void ProcessData(byte *outString, const byte *inString, unsigned int length); + void Resynchronize(const byte *iv); + unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();} + unsigned int GetOptimalNextBlockSize() const {return m_leftOver;} + unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();} + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return false;} + +protected: + typedef typename BASE::PolicyInterface PolicyInterface; + + virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0; + + void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length); + + unsigned int m_leftOver; +}; + +template > +class CFB_EncryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return true;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); +}; + +template > +class CFB_DecryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return false;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); +}; + +template +class SymmetricCipherFinalTemplate : public AlgorithmImpl, INFO> +{ +public: + SymmetricCipherFinalTemplate() {} + SymmetricCipherFinalTemplate(const byte *key) + {SetKey(key, DEFAULT_KEYLENGTH);} + SymmetricCipherFinalTemplate(const byte *key, unsigned int length) + {SetKey(key, length);} + SymmetricCipherFinalTemplate(const byte *key, unsigned int length, const byte *iv) + {SetKey(key, length); Resynchronize(iv);} + + void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms = g_nullNameValuePairs) + { + ThrowIfInvalidKeyLength(length); + UncheckedSetKey(params, key, length); + } + + Clonable * Clone() {return new SymmetricCipherFinalTemplate(*this);} +}; + +template +void AdditiveCipherTemplate::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) +{ + PolicyInterface &policy = AccessPolicy(); + policy.CipherSetKey(params, key, length); + m_buffer.New(GetBufferByteSize(policy)); + m_leftOver = 0; +} + +template +void CFB_CipherTemplate::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) +{ + PolicyInterface &policy = AccessPolicy(); + policy.CipherSetKey(params, key, length); + m_leftOver = policy.GetBytesPerIteration(); +} + +NAMESPACE_END + +#endif -- cgit v1.2.1