00001
00002
00003 #include "pch.h"
00004 #include "panama.h"
00005
00006 NAMESPACE_BEGIN(CryptoPP)
00007
00008 static const unsigned int STAGES = 32;
00009
00010 Panama::Panama()
00011 : m_state(17*2 + STAGES*sizeof(Stage))
00012 {
00013 Reset();
00014 }
00015
00016 void Panama::Reset()
00017 {
00018 m_bstart = 0;
00019 memset(m_state, 0, m_state.size*4);
00020 }
00021
00022 void Panama::Iterate(unsigned int count, const word32 *p, word32 *z, const word32 *y)
00023 {
00024 unsigned int bstart = m_bstart;
00025 word32 *const a = m_state;
00026 #define c (a+17)
00027 #define b ((Stage *)(a+34))
00028
00029
00030 #define OA(i) z[i] = a[i+9]
00031 #define OX(i) z[i] = y[i] ^ a[i+9]
00032
00033 #define US(i) {word32 t=b0[i]; b0[i]=p[i]^t; b25[(i+6)%8]^=t;}
00034 #define UL(i) {word32 t=b0[i]; b0[i]=a[i+1]^t; b25[(i+6)%8]^=t;}
00035
00036 #define GP(i) c[5*i%17] = rotlFixed(a[i] ^ (a[(i+1)%17] | ~a[(i+2)%17]), ((5*i%17)*((5*i%17)+1)/2)%32)
00037
00038 #define T(i,x) a[i] = c[i] ^ c[(i+1)%17] ^ c[(i+4)%17] ^ x
00039 #define TS1S(i) T(i+1, p[i])
00040 #define TS1L(i) T(i+1, b4[i])
00041 #define TS2(i) T(i+9, b16[i])
00042
00043 while (count--)
00044 {
00045 if (z)
00046 {
00047 if (y)
00048 {
00049 OX(0); OX(1); OX(2); OX(3); OX(4); OX(5); OX(6); OX(7);
00050 y += 8;
00051 }
00052 else
00053 {
00054 OA(0); OA(1); OA(2); OA(3); OA(4); OA(5); OA(6); OA(7);
00055 }
00056 z += 8;
00057 }
00058
00059 word32 *const b16 = b[(bstart+16) % STAGES];
00060 word32 *const b4 = b[(bstart+4) % STAGES];
00061 bstart = (bstart + STAGES - 1) % STAGES;
00062 word32 *const b0 = b[bstart];
00063 word32 *const b25 = b[(bstart+25) % STAGES];
00064
00065
00066 if (p)
00067 {
00068 US(0); US(1); US(2); US(3); US(4); US(5); US(6); US(7);
00069 }
00070 else
00071 {
00072 UL(0); UL(1); UL(2); UL(3); UL(4); UL(5); UL(6); UL(7);
00073 }
00074
00075 GP(0); GP(1); GP(2); GP(3); GP(4); GP(5); GP(6); GP(7);
00076 GP(8); GP(9); GP(10); GP(11); GP(12); GP(13); GP(14); GP(15); GP(16);
00077
00078 T(0,1);
00079
00080 if (p)
00081 {
00082 TS1S(0); TS1S(1); TS1S(2); TS1S(3); TS1S(4); TS1S(5); TS1S(6); TS1S(7);
00083 p += 8;
00084 }
00085 else
00086 {
00087 TS1L(0); TS1L(1); TS1L(2); TS1L(3); TS1L(4); TS1L(5); TS1L(6); TS1L(7);
00088 }
00089
00090 TS2(0); TS2(1); TS2(2); TS2(3); TS2(4); TS2(5); TS2(6); TS2(7);
00091 }
00092 m_bstart = bstart;
00093 }
00094
00095 template <bool H>
00096 unsigned int PanamaHash<H>::HashMultipleBlocks(const word32 *input, unsigned int length)
00097 {
00098 if (CheckEndianess(HIGHFIRST))
00099 {
00100 Iterate(length / BLOCKSIZE, input);
00101 return length % BLOCKSIZE;
00102 }
00103 else
00104 return IteratedHashBase<word32>::HashMultipleBlocks(input, length);
00105 }
00106
00107 template <bool H>
00108 void PanamaHash<H>::Final(byte *hash)
00109 {
00110 PadLastBlock(BLOCKSIZE, 0x01);
00111 CorrectEndianess(data, data, BLOCKSIZE);
00112
00113 vTransform(data);
00114
00115 Iterate(32);
00116
00117 CorrectEndianess(m_state+9, m_state+9, DigestSize());
00118 memcpy(hash, m_state+9, DigestSize());
00119
00120 Reinit();
00121 }
00122
00123 template <bool H>
00124 PanamaCipher<H>::PanamaCipher(const byte *key, const byte *iv)
00125 : m_buf(8), m_leftOver(0)
00126 {
00127 memcpy(m_buf, key, 32);
00128 CorrectEndianess(m_buf, m_buf, 32);
00129 Iterate(1, m_buf);
00130 if (iv)
00131 {
00132 memcpy(m_buf, iv, 32);
00133 CorrectEndianess(m_buf, m_buf, 32);
00134 }
00135 else
00136 memset(m_buf, 0, 32);
00137 Iterate(1, m_buf);
00138
00139 Iterate(32);
00140 }
00141
00142 template <bool H>
00143 void PanamaCipher<H>::ProcessString(byte *outString, const byte *inString, unsigned int length)
00144 {
00145 if (m_leftOver > 0)
00146 {
00147 unsigned int len = STDMIN(m_leftOver, length);
00148 xorbuf(outString, inString, (byte *)(m_buf+m_buf.size)-m_leftOver, len);
00149 length -= len;
00150 m_leftOver -= len;
00151 inString += len;
00152 outString += len;
00153 }
00154
00155 if (CheckEndianess(HIGHFIRST) && IsAligned<word32>(outString))
00156 {
00157 if (!IsAligned<word32>(inString))
00158 {
00159 memcpy(outString, inString, length);
00160 inString = outString;
00161 }
00162 Iterate(length / 32, NULL, (word32 *)outString, (const word32 *)inString);
00163 inString += length - length % 32;
00164 outString += length - length % 32;
00165 length %= 32;
00166 }
00167
00168 while (length)
00169 {
00170 Iterate(1, NULL, m_buf);
00171 CorrectEndianess(m_buf, m_buf, 32);
00172 unsigned int len = STDMIN(32U, length);
00173 xorbuf(outString, inString, (byte *)m_buf.ptr, len);
00174 length -= len;
00175 m_leftOver = 32 - len;
00176 inString += len;
00177 outString += len;
00178 }
00179 }
00180
00181 template class PanamaHash<true>;
00182 template class PanamaHash<false>;
00183
00184 template class PanamaCipher<true>;
00185 template class PanamaCipher<false>;
00186
00187 NAMESPACE_END