salsa.cpp

00001 // salsa.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "salsa.h"
00005 #include "misc.h"
00006 #include "argnames.h"
00007 
00008 NAMESPACE_BEGIN(CryptoPP)
00009 
00010 void Salsa20_TestInstantiations()
00011 {
00012         Salsa20::Encryption x;
00013 }
00014 
00015 void Salsa20_Policy::CipherGetNextIV(byte *IV)
00016 {
00017         word32 j6 = m_state[6] + 1;
00018         word32 j7 = m_state[7] + (j6 == 0);
00019 
00020         UnalignedPutWord(LITTLE_ENDIAN_ORDER, IV, j6);
00021         UnalignedPutWord(LITTLE_ENDIAN_ORDER, IV+4, j7);
00022 }
00023 
00024 void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
00025 {
00026         m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
00027 
00028         if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
00029                 throw InvalidRounds(StaticAlgorithmName(), m_rounds);
00030 
00031         GetUserKey(LITTLE_ENDIAN_ORDER, m_state+1, 4, key, 16);
00032         GetUserKey(LITTLE_ENDIAN_ORDER, m_state+11, 4, key + length - 16, 16);
00033 
00034         // m_state[0,5,10,15] forms "expand 16-byte k" or "expand 32-byte k"
00035         m_state[0] = 0x61707865;
00036         m_state[5] = (length == 16) ? 0x3120646e : 0x3320646e;
00037         m_state[10] = (length == 16) ? 0x79622d36 : 0x79622d32;
00038         m_state[15] = 0x6b206574;
00039 }
00040 
00041 void Salsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV)
00042 {
00043         GetUserKey(LITTLE_ENDIAN_ORDER, m_state+6, 4, IV, 8);
00044 }
00045 
00046 void Salsa20_Policy::SeekToIteration(lword iterationCount)
00047 {
00048         m_state[8] = (word32)iterationCount;
00049         m_state[9] = (word32)SafeRightShift<32>(iterationCount);
00050 }
00051 
00052 void Salsa20_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00053 {
00054         KeystreamOutput<LittleEndian> keystreamOutput(operation, output, input);
00055 
00056         word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
00057         word32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
00058 
00059         j0 = m_state[0];
00060         j1 = m_state[1];
00061         j2 = m_state[2];
00062         j3 = m_state[3];
00063         j4 = m_state[4];
00064         j5 = m_state[5];
00065         j6 = m_state[6];
00066         j7 = m_state[7];
00067         j8 = m_state[8];
00068         j9 = m_state[9];
00069         j10 = m_state[10];
00070         j11 = m_state[11];
00071         j12 = m_state[12];
00072         j13 = m_state[13];
00073         j14 = m_state[14];
00074         j15 = m_state[15];
00075 
00076         for (size_t iteration = 0; iteration < iterationCount; ++iteration)
00077         {
00078                 x0 = j0;
00079                 x1 = j1;
00080                 x2 = j2;
00081                 x3 = j3;
00082                 x4 = j4;
00083                 x5 = j5;
00084                 x6 = j6;
00085                 x7 = j7;
00086                 x8 = j8;
00087                 x9 = j9;
00088                 x10 = j10;
00089                 x11 = j11;
00090                 x12 = j12;
00091                 x13 = j13;
00092                 x14 = j14;
00093                 x15 = j15;
00094 
00095                 for (int i=m_rounds; i>0; i-=2)
00096                 {
00097 #define QUARTER_ROUND(a, b, c, d)       \
00098         b = b ^ rotlFixed(a + d, 7);    \
00099         c = c ^ rotlFixed(b + a, 9);    \
00100         d = d ^ rotlFixed(c + b, 13);   \
00101         a = a ^ rotlFixed(d + c, 18);
00102 
00103                         QUARTER_ROUND(x0, x4, x8, x12)
00104                         QUARTER_ROUND(x5, x9, x13, x1)
00105                         QUARTER_ROUND(x10, x14, x2, x6)
00106                         QUARTER_ROUND(x15, x3, x7, x11)
00107 
00108                         QUARTER_ROUND(x0, x1, x2, x3)
00109                         QUARTER_ROUND(x5, x6, x7, x4)
00110                         QUARTER_ROUND(x10, x11, x8, x9)
00111                         QUARTER_ROUND(x15, x12, x13, x14)
00112                 }
00113 
00114                 keystreamOutput (x0 + j0)
00115                                                 (x1 + j1)
00116                                                 (x2 + j2)
00117                                                 (x3 + j3)
00118                                                 (x4 + j4)
00119                                                 (x5 + j5)
00120                                                 (x6 + j6)
00121                                                 (x7 + j7)
00122                                                 (x8 + j8)
00123                                                 (x9 + j9)
00124                                                 (x10 + j10)
00125                                                 (x11 + j11)
00126                                                 (x12 + j12)
00127                                                 (x13 + j13)
00128                                                 (x14 + j14)
00129                                                 (x15 + j15);
00130 
00131                 if (++j8 == 0)
00132                         ++j9;
00133         }
00134 
00135         m_state[8] = j8;
00136         m_state[9] = j9;
00137 }
00138 
00139 NAMESPACE_END

Generated on Sat Dec 23 02:07:10 2006 for Crypto++ by  doxygen 1.5.1-p1