00001
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 ¶ms, 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
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