void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length) { unsigned int s = BlockSize(); assert(length % s == 0); unsigned int alignment = m_cipher->BlockAlignment(); bool inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment); if (IsAlignedOn(outString, alignment)) { if (inputAlignmentOk) ProcessBlocks(outString, inString, length / s); else { memcpy(outString, inString, length); ProcessBlocks(outString, outString, length / s); } } else { while (length) { if (inputAlignmentOk) ProcessBlocks(m_buffer, inString, 1); else { memcpy(m_buffer, inString, s); ProcessBlocks(m_buffer, m_buffer, 1); } memcpy(outString, m_buffer, s); inString += s; outString += s; length -= s; } } }
inline SharkProcessAndXorBlock(const word64 *roundKeys, unsigned int rounds, const byte *inBlock, const byte *xorBlock, byte *outBlock) { CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf<word64>())); word64 tmp = *(word64 *)(void *)inBlock ^ roundKeys[0]; ByteOrder order = GetNativeByteOrder(); tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)] ^ roundKeys[1]; for(unsigned int i=2; i<rounds; i++) { tmp = cbox[0][GETBYTE(tmp, 7)] ^ cbox[1][GETBYTE(tmp, 6)] ^ cbox[2][GETBYTE(tmp, 5)] ^ cbox[3][GETBYTE(tmp, 4)] ^ cbox[4][GETBYTE(tmp, 3)] ^ cbox[5][GETBYTE(tmp, 2)] ^ cbox[6][GETBYTE(tmp, 1)] ^ cbox[7][GETBYTE(tmp, 0)] ^ roundKeys[i]; } PutBlock<byte, BigEndian>(xorBlock, outBlock) (sbox[GETBYTE(tmp, 7)]) (sbox[GETBYTE(tmp, 6)]) (sbox[GETBYTE(tmp, 5)]) (sbox[GETBYTE(tmp, 4)]) (sbox[GETBYTE(tmp, 3)]) (sbox[GETBYTE(tmp, 2)]) (sbox[GETBYTE(tmp, 1)]) (sbox[GETBYTE(tmp, 0)]); CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf<word64>())); *(word64 *)(void *)outBlock ^= roundKeys[rounds]; }};
inline void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inString, unsigned int length) { if (m_leftOver > 0) { unsigned int len = STDMIN(m_leftOver, length); xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len); length -= len; m_leftOver -= len; inString += len; outString += len; } if (!length) return; assert(m_leftOver == 0); PolicyInterface &policy = this->AccessPolicy(); unsigned int bytesPerIteration = policy.GetBytesPerIteration(); unsigned int alignment = policy.GetAlignment(); if (policy.CanOperateKeystream() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) { if (IsAlignedOn(inString, alignment)) policy.OperateKeystream(XOR_KEYSTREAM, outString, inString, length / bytesPerIteration); else { memcpy(outString, inString, length); policy.OperateKeystream(XOR_KEYSTREAM_INPLACE, outString, outString, length / bytesPerIteration); } inString += length - length % bytesPerIteration; outString += length - length % bytesPerIteration; length %= bytesPerIteration; if (!length) return; } unsigned int bufferByteSize = GetBufferByteSize(policy); unsigned int bufferIterations = policy.GetIterationsToBuffer(); while (length >= bufferByteSize) { policy.WriteKeystream(m_buffer, bufferIterations); xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); length -= bufferByteSize; inString += bufferByteSize; outString += bufferByteSize; } if (length > 0) { policy.WriteKeystream(m_buffer, bufferIterations); xorbuf(outString, inString, KeystreamBufferBegin(), length); m_leftOver = bytesPerIteration - length; } }
void CFB_CipherTemplate<BASE>::ProcessData(byte *outString, const byte *inString, unsigned int length) { assert(length % this->MandatoryBlockSize() == 0); PolicyInterface &policy = this->AccessPolicy(); unsigned int bytesPerIteration = policy.GetBytesPerIteration(); unsigned int alignment = policy.GetAlignment(); byte *reg = policy.GetRegisterBegin(); if (m_leftOver) { unsigned int len = STDMIN(m_leftOver, length); CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len); m_leftOver -= len; length -= len; inString += len; outString += len; } if (!length) return; assert(m_leftOver == 0); if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) { if (IsAlignedOn(inString, alignment)) policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration); else { memcpy(outString, inString, length); policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration); } inString += length - length % bytesPerIteration; outString += length - length % bytesPerIteration; length %= bytesPerIteration; } while (length >= bytesPerIteration) { policy.TransformRegister(); CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); length -= bytesPerIteration; inString += bytesPerIteration; outString += bytesPerIteration; } if (length > 0) { policy.TransformRegister(); CombineMessageAndShiftRegister(outString, reg, inString, length); m_leftOver = bytesPerIteration - length; } }
bool Socket::Connect(const char *addr, unsigned int port) { assert(addr != NULL); sockaddr_in sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr(addr); if (sa.sin_addr.s_addr == INADDR_NONE) { hostent *lphost = gethostbyname(addr); if (lphost == NULL) { SetLastError(SOCKET_EINVAL); CheckAndHandleError_int("gethostbyname", SOCKET_ERROR); } else { assert(IsAlignedOn(lphost->h_addr,GetAlignmentOf<in_addr>())); sa.sin_addr.s_addr = ((in_addr *)(void *)lphost->h_addr)->s_addr; } } sa.sin_port = htons((u_short)port); return Connect((const sockaddr *)&sa, sizeof(sa)); }
void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inString, size_t length) { if (m_leftOver > 0) { size_t len = STDMIN(m_leftOver, length); xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len); length -= len; m_leftOver -= len; inString += len; outString += len; if (!length) return; } CRYPTOPP_ASSERT(m_leftOver == 0); PolicyInterface &policy = this->AccessPolicy(); unsigned int bytesPerIteration = policy.GetBytesPerIteration(); if (policy.CanOperateKeystream() && length >= bytesPerIteration) { size_t iterations = length / bytesPerIteration; unsigned int alignment = policy.GetAlignment(); KeystreamOperation operation = KeystreamOperation((IsAlignedOn(inString, alignment) * 2) | (int)IsAlignedOn(outString, alignment)); policy.OperateKeystream(operation, outString, inString, iterations); inString += iterations * bytesPerIteration; outString += iterations * bytesPerIteration; length -= iterations * bytesPerIteration; if (!length) return; } size_t bufferByteSize = m_buffer.size(); size_t bufferIterations = bufferByteSize / bytesPerIteration; while (length >= bufferByteSize) { policy.WriteKeystream(m_buffer, bufferIterations); xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); length -= bufferByteSize; inString += bufferByteSize; outString += bufferByteSize; } if (length > 0) { bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); bufferIterations = bufferByteSize / bytesPerIteration; policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length); m_leftOver = bufferByteSize - length; } }
void Camellia::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { #define KS(i, j) ks[i*4 + EFI(j/2)*2 + EFI(j%2)] #define FL(klh, kll, krh, krl) \ ll ^= rotlFixed(lh & klh, 1); \ lh ^= (ll | kll); \ rh ^= (rl | krl); \ rl ^= rotlFixed(rh & krh, 1); word32 lh, ll, rh, rl; typedef BlockGetAndPut<word32, BigEndian> Block; Block::Get(inBlock)(lh)(ll)(rh)(rl); const word32 *ks = m_key.data(); lh ^= KS(0,0); ll ^= KS(0,1); rh ^= KS(0,2); rl ^= KS(0,3); // timing attack countermeasure. see comments at top for more details const int cacheLineSize = GetCacheLineSize(); unsigned int i; volatile word32 _u = 0; word32 u = _u; assert(IsAlignedOn(s1,GetAlignmentOf<word32>())); for (i=0; i<256; i+=cacheLineSize) u &= *(const word32 *)(void*)(s1+i); u &= *(const word32 *)(void*)(s1+252); lh |= u; ll |= u; SLOW_ROUND(lh, ll, rh, rl, KS(1,0), KS(1,1)) SLOW_ROUND(rh, rl, lh, ll, KS(1,2), KS(1,3)) for (i = m_rounds-1; i > 0; --i) { DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) DOUBLE_ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1), KS(3,2), KS(3,3)) FL(KS(4,0), KS(4,1), KS(4,2), KS(4,3)); DOUBLE_ROUND(lh, ll, rh, rl, KS(5,0), KS(5,1), KS(5,2), KS(5,3)) ks += 16; } DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1)) SLOW_ROUND(rh, rl, lh, ll, KS(3,2), KS(3,3)) lh ^= KS(4,0); ll ^= KS(4,1); rh ^= KS(4,2); rl ^= KS(4,3); Block::Put(xorBlock, outBlock)(rh)(rl)(lh)(ll); }
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); } }
inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround { return IsAlignedOn(p, GetAlignmentOf<T>()); }
void CFB_CipherTemplate<BASE>::ProcessData(byte *outString, const byte *inString, size_t length) { CRYPTOPP_ASSERT(outString); CRYPTOPP_ASSERT(inString); CRYPTOPP_ASSERT(length % this->MandatoryBlockSize() == 0); PolicyInterface &policy = this->AccessPolicy(); word32 bytesPerIteration = policy.GetBytesPerIteration(); byte *reg = policy.GetRegisterBegin(); if (m_leftOver) { const size_t len = STDMIN(m_leftOver, length); CombineMessageAndShiftRegister(outString, PtrAdd(reg, bytesPerIteration - m_leftOver), inString, len); m_leftOver -= len; length -= len; inString = PtrAdd(inString, len); outString = PtrAdd(outString, len); } // TODO: Figure out what is happening on ARM A-32. x86, Aarch64 and PowerPC are OK. // The issue surfaced for CFB mode when we cut-in Cryptogams AES ARMv7 asm. // Using 'outString' for both input and output leads to incorrect results. // // Benchmarking on Cortex-A7 and Cortex-A9 indicates removing the block // below costs about 9 cpb for CFB mode on ARM. // // Also see https://github.com/weidai11/cryptopp/issues/683. // // UPDATE: It appears the issue is related to alignment checks. When we made // the alignment check result volatile GCC and Clang stopped short- // circuiting the transform, which is what we wanted. I suspect // there's a little more to the issue, but we can enable the block again. const unsigned int alignment = policy.GetAlignment(); volatile bool isAligned = IsAlignedOn(outString, alignment); if (policy.CanIterate() && length >= bytesPerIteration && isAligned) { isAligned &= IsAlignedOn(inString, alignment); const CipherDir cipherDir = GetCipherDir(*this); if (isAligned) policy.Iterate(outString, inString, cipherDir, length / bytesPerIteration); else { // GCC and Clang does not like this on ARM. The incorrect result is a string // of 0's instead of ciphertext (or plaintext if decrypting). The 0's trace // back to the allocation for the std::string in datatest.cpp. Elements in the // string are initialized to their default value, which is 0. // // It almost feels as if the compiler does not see the string is transformed // in-place so it short-circuits the transform. However, if we use a stand-alone // reproducer with the same data then the issue is _not_ present. // // When working on this issue we introduced PtrAdd and PtrSub to ensure we were // not running afoul of pointer arithmetic rules of the language. Namely we need // to use ptrdiff_t when subtracting pointers. We believe the relevant code paths // are clean. // // One workaround is a distinct and aligned temporary buffer. It [mostly] works // as expected but requires an extra allocation (casts not shown): // // std::string temp(inString, length); // policy.Iterate(outString, &temp[0], cipherDir, length / bytesPerIteration); // memcpy(outString, inString, length); policy.Iterate(outString, outString, cipherDir, length / bytesPerIteration); } const size_t remainder = length % bytesPerIteration; inString = PtrAdd(inString, length - remainder); outString = PtrAdd(outString, length - remainder); length = remainder; } while (length >= bytesPerIteration) { policy.TransformRegister(); CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); length -= bytesPerIteration; inString = PtrAdd(inString, bytesPerIteration); outString = PtrAdd(outString, bytesPerIteration); } if (length > 0) { policy.TransformRegister(); CombineMessageAndShiftRegister(outString, reg, inString, length); m_leftOver = bytesPerIteration - length; } }