Crypto++
square.cpp
1 // square.cpp - written and placed in the public domain by Wei Dai
2 // Based on Paulo S.L.M. Barreto's public domain implementation
3 
4 #include "pch.h"
5 #include "square.h"
6 #include "misc.h"
7 #include "gf256.h"
8 
9 NAMESPACE_BEGIN(CryptoPP)
10 
11 // apply theta to a roundkey
12 static void SquareTransform (word32 in[4], word32 out[4])
13 {
14  static const byte G[4][4] =
15  {
16  0x02U, 0x01U, 0x01U, 0x03U,
17  0x03U, 0x02U, 0x01U, 0x01U,
18  0x01U, 0x03U, 0x02U, 0x01U,
19  0x01U, 0x01U, 0x03U, 0x02U
20  };
21 
22  GF256 gf256(0xf5);
23 
24  for (int i = 0; i < 4; i++)
25  {
26  word32 temp = 0;
27  for (int j = 0; j < 4; j++)
28  for (int k = 0; k < 4; k++)
29  temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8);
30  out[i] = temp;
31  }
32 }
33 
34 #define roundkeys(i, j) m_roundkeys[(i)*4+(j)]
35 #define roundkeys4(i) (m_roundkeys+(i)*4)
36 
37 void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
38 {
39  AssertValidKeyLength(length);
40 
41  static const word32 offset[ROUNDS] = {
42  0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
43  0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
44  };
45 
46  GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH);
47 
48  /* apply the key evolution function */
49  for (int i = 1; i < ROUNDS+1; i++)
50  {
51  roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlFixed(roundkeys(i-1, 3), 8U) ^ offset[i-1];
52  roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0);
53  roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1);
54  roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2);
55  }
56 
57  /* produce the round keys */
58  if (IsForwardTransformation())
59  {
60  for (int i = 0; i < ROUNDS; i++)
61  SquareTransform (roundkeys4(i), roundkeys4(i));
62  }
63  else
64  {
65  for (int i = 0; i < ROUNDS/2; i++)
66  for (int j = 0; j < 4; j++)
67  std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j));
68  SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS));
69  }
70 }
71 
72 #define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */
73 #define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */
74 #define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */
75 #define LSB(x) (((x) ) & 0xffU) /* least significant byte */
76 
77 #define squareRound(text, temp, T0, T1, T2, T3, roundkey) \
78 { \
79  temp[0] = T0[MSB (text[0])] \
80  ^ T1[MSB (text[1])] \
81  ^ T2[MSB (text[2])] \
82  ^ T3[MSB (text[3])] \
83  ^ roundkey[0]; \
84  temp[1] = T0[SSB (text[0])] \
85  ^ T1[SSB (text[1])] \
86  ^ T2[SSB (text[2])] \
87  ^ T3[SSB (text[3])] \
88  ^ roundkey[1]; \
89  temp[2] = T0[TSB (text[0])] \
90  ^ T1[TSB (text[1])] \
91  ^ T2[TSB (text[2])] \
92  ^ T3[TSB (text[3])] \
93  ^ roundkey[2]; \
94  temp[3] = T0[LSB (text[0])] \
95  ^ T1[LSB (text[1])] \
96  ^ T2[LSB (text[2])] \
97  ^ T3[LSB (text[3])] \
98  ^ roundkey[3]; \
99 } /* squareRound */
100 
101 #define squareFinal(text, temp, S, roundkey) \
102 { \
103  text[0] = ((word32) (S[MSB (temp[0])]) << 24) \
104  ^ ((word32) (S[MSB (temp[1])]) << 16) \
105  ^ ((word32) (S[MSB (temp[2])]) << 8) \
106  ^ (word32) (S[MSB (temp[3])]) \
107  ^ roundkey[0]; \
108  text[1] = ((word32) (S[SSB (temp[0])]) << 24) \
109  ^ ((word32) (S[SSB (temp[1])]) << 16) \
110  ^ ((word32) (S[SSB (temp[2])]) << 8) \
111  ^ (word32) (S[SSB (temp[3])]) \
112  ^ roundkey[1]; \
113  text[2] = ((word32) (S[TSB (temp[0])]) << 24) \
114  ^ ((word32) (S[TSB (temp[1])]) << 16) \
115  ^ ((word32) (S[TSB (temp[2])]) << 8) \
116  ^ (word32) (S[TSB (temp[3])]) \
117  ^ roundkey[2]; \
118  text[3] = ((word32) (S[LSB (temp[0])]) << 24) \
119  ^ ((word32) (S[LSB (temp[1])]) << 16) \
120  ^ ((word32) (S[LSB (temp[2])]) << 8) \
121  ^ (word32) (S[LSB (temp[3])]) \
122  ^ roundkey[3]; \
123 } /* squareFinal */
124 
126 
127 void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
128 {
129  word32 text[4], temp[4];
130  Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
131 
132  /* initial key addition */
133  text[0] ^= roundkeys(0, 0);
134  text[1] ^= roundkeys(0, 1);
135  text[2] ^= roundkeys(0, 2);
136  text[3] ^= roundkeys(0, 3);
137 
138  /* ROUNDS - 1 full rounds */
139  for (int i=1; i+1<ROUNDS; i+=2)
140  {
141  squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i));
142  squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1));
143  }
144  squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1));
145 
146  /* last round (diffusion becomes only transposition) */
147  squareFinal (text, temp, Se, roundkeys4(ROUNDS));
148 
149  Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
150 }
151 
152 void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
153 {
154  word32 text[4], temp[4];
155  Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
156 
157  /* initial key addition */
158  text[0] ^= roundkeys(0, 0);
159  text[1] ^= roundkeys(0, 1);
160  text[2] ^= roundkeys(0, 2);
161  text[3] ^= roundkeys(0, 3);
162 
163  /* ROUNDS - 1 full rounds */
164  for (int i=1; i+1<ROUNDS; i+=2)
165  {
166  squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i));
167  squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1));
168  }
169  squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1));
170 
171  /* last round (diffusion becomes only transposition) */
172  squareFinal (text, temp, Sd, roundkeys4(ROUNDS));
173 
174  Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
175 }
176 
177 NAMESPACE_END
GF(256) with polynomial basis.
Definition: gf256.h:9
interface for retrieving values given their names
Definition: cryptlib.h:225