$OpenBSD: patch-panama_cpp,v 1.1 2011/06/24 07:55:18 dcoppa Exp $

Fix for Panama cipher validation failure (upstream rev 526).
Bug report is about armel, but it has been proven to also prevent
a sigbus crash on sparc64.

--- panama.cpp.orig	Mon Aug  9 14:22:42 2010
+++ panama.cpp	Wed Jun  8 16:42:01 2011
@@ -313,7 +313,7 @@ void CRYPTOPP_NOINLINE Panama_SSE2_Pull(size_t count, 
 #ifndef CRYPTOPP_GENERATE_X64_MASM
 
 template <class B>
-void Panama<B>::Iterate(size_t count, const word32 *p, word32 *z, const word32 *y)
+void Panama<B>::Iterate(size_t count, const word32 *p, byte *output, const byte *input, KeystreamOperation operation)
 {
 	word32 bstart = m_state[17];
 	word32 *const aPtr = m_state;
@@ -329,9 +329,6 @@ void Panama<B>::Iterate(size_t count, const word32 *p,
 // b: 0 4 | 1 5 | 2 6 | 3 7
 #define b(i, j) b##i[(j)*2%8 + (j)/4]
 
-// output
-#define OA(i) z[i] = ConditionalByteReverse(B::ToEnum(), a(i+9))
-#define OX(i) z[i] = y[i] ^ ConditionalByteReverse(B::ToEnum(), a(i+9))
 // buffer update
 #define US(i) {word32 t=b(0,i); b(0,i)=ConditionalByteReverse(B::ToEnum(), p[i])^t; b(25,(i+6)%8)^=t;}
 #define UL(i) {word32 t=b(0,i); b(0,i)=a(i+1)^t; b(25,(i+6)%8)^=t;}
@@ -345,18 +342,20 @@ void Panama<B>::Iterate(size_t count, const word32 *p,
 
 	while (count--)
 	{
-		if (z)
+		if (output)
 		{
-			if (y)
-			{
-				OX(0); OX(1); OX(2); OX(3); OX(4); OX(5); OX(6); OX(7);
-				y += 8;
-			}
-			else
-			{
-				OA(0); OA(1); OA(2); OA(3); OA(4); OA(5); OA(6); OA(7);
-			}
-			z += 8;
+#define PANAMA_OUTPUT(x)	\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, a(0+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, a(1+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, a(2+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a(3+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 4, a(4+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 5, a(5+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 6, a(6+9));\
+	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 7, a(7+9));
+
+			typedef word32 WordType;
+			CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(PANAMA_OUTPUT, 4*8);
 		}
 
 		word32 *const b16 = (word32 *)(bPtr+((bstart+16*32) & 31*32));
@@ -422,14 +421,14 @@ void PanamaHash<B>::TruncatedFinal(byte *hash, size_t 
 {
 	this->ThrowIfInvalidTruncatedSize(size);
 
-	PadLastBlock(this->BLOCKSIZE, 0x01);
+	this->PadLastBlock(this->BLOCKSIZE, 0x01);
 	
 	HashEndianCorrectedBlock(this->m_data);
 
 	this->Iterate(32);	// pull
 
 	FixedSizeSecBlock<word32, 8> buf;
-	this->Iterate(1, NULL, buf, NULL);
+	this->Iterate(1, NULL, buf.BytePtr(), NULL);
 
 	memcpy(hash, buf, size);
 
@@ -491,7 +490,7 @@ void PanamaCipherPolicy<B>::OperateKeystream(Keystream
 		Panama_SSE2_Pull(iterationCount, this->m_state, (word32 *)output, (const word32 *)input);
 	else
 #endif
-		this->Iterate(iterationCount, NULL, (word32 *)output, (const word32 *)input);
+		this->Iterate(iterationCount, NULL, output, input, operation);
 }
 
 template class Panama<BigEndian>;
