Line | Count | Source |
1 | | // square.cpp - originally 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 "config.h" |
6 | | |
7 | | #include "square.h" |
8 | | #include "misc.h" |
9 | | #include "gf256.h" |
10 | | |
11 | | #if CRYPTOPP_MSC_VERSION |
12 | | # pragma warning(disable: 4244) |
13 | | #endif |
14 | | |
15 | | #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE |
16 | | # pragma GCC diagnostic ignored "-Wmissing-braces" |
17 | | #endif |
18 | | |
19 | | NAMESPACE_BEGIN(CryptoPP) |
20 | | |
21 | | // apply theta to a roundkey |
22 | | static void SquareTransform (word32 in[4], word32 out[4]) |
23 | 41 | { |
24 | 41 | static const byte G[4][4] = |
25 | 41 | { |
26 | 41 | {0x02U, 0x01U, 0x01U, 0x03U}, |
27 | 41 | {0x03U, 0x02U, 0x01U, 0x01U}, |
28 | 41 | {0x01U, 0x03U, 0x02U, 0x01U}, |
29 | 41 | {0x01U, 0x01U, 0x03U, 0x02U} |
30 | 41 | }; |
31 | | |
32 | 41 | GF256 gf256(0xf5); |
33 | | |
34 | 205 | for (int i = 0; i < 4; i++) |
35 | 164 | { |
36 | 164 | word32 temp = 0; |
37 | 820 | for (unsigned int j = 0; j < 4; j++) |
38 | 3.28k | for (unsigned int k = 0; k < 4; k++) |
39 | 2.62k | temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8); |
40 | 164 | out[i] = temp; |
41 | 164 | } |
42 | 41 | } |
43 | | |
44 | 3.26k | #define roundkeys(i, j) m_roundkeys[(i)*4+(j)] |
45 | 82 | #define roundkeys4(i) (m_roundkeys+(i)*4) |
46 | | |
47 | | void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) |
48 | 6 | { |
49 | 6 | AssertValidKeyLength(length); |
50 | | |
51 | 6 | static const word32 offset[ROUNDS] = { |
52 | 6 | 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, |
53 | 6 | 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, |
54 | 6 | }; |
55 | | |
56 | 6 | GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH); |
57 | | |
58 | | /* apply the key evolution function */ |
59 | 54 | for (int i = 1; i < ROUNDS+1; i++) |
60 | 48 | { |
61 | 48 | roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlConstant<8>(roundkeys(i-1, 3)) ^ offset[i-1]; |
62 | 48 | roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0); |
63 | 48 | roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1); |
64 | 48 | roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2); |
65 | 48 | } |
66 | | |
67 | | /* produce the round keys */ |
68 | 6 | if (IsForwardTransformation()) |
69 | 5 | { |
70 | 45 | for (int i = 0; i < ROUNDS; i++) |
71 | 40 | SquareTransform (roundkeys4(i), roundkeys4(i)); |
72 | 5 | } |
73 | 1 | else |
74 | 1 | { |
75 | 5 | for (int i = 0; i < ROUNDS/2; i++) |
76 | 20 | for (int j = 0; j < 4; j++) |
77 | 16 | std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j)); |
78 | 1 | SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS)); |
79 | 1 | } |
80 | 6 | } |
81 | | |
82 | 21.2k | #define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */ |
83 | 21.2k | #define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */ |
84 | 21.2k | #define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */ |
85 | 21.2k | #define LSB(x) (((x) ) & 0xffU) /* least significant byte */ |
86 | | |
87 | 4.65k | #define squareRound(text, temp, T0, T1, T2, T3, roundkey) \ |
88 | 4.65k | { \ |
89 | 4.65k | temp[0] = T0[MSB (text[0])] \ |
90 | 4.65k | ^ T1[MSB (text[1])] \ |
91 | 4.65k | ^ T2[MSB (text[2])] \ |
92 | 4.65k | ^ T3[MSB (text[3])] \ |
93 | 4.65k | ^ roundkey[0]; \ |
94 | 4.65k | temp[1] = T0[SSB (text[0])] \ |
95 | 4.65k | ^ T1[SSB (text[1])] \ |
96 | 4.65k | ^ T2[SSB (text[2])] \ |
97 | 4.65k | ^ T3[SSB (text[3])] \ |
98 | 4.65k | ^ roundkey[1]; \ |
99 | 4.65k | temp[2] = T0[TSB (text[0])] \ |
100 | 4.65k | ^ T1[TSB (text[1])] \ |
101 | 4.65k | ^ T2[TSB (text[2])] \ |
102 | 4.65k | ^ T3[TSB (text[3])] \ |
103 | 4.65k | ^ roundkey[2]; \ |
104 | 4.65k | temp[3] = T0[LSB (text[0])] \ |
105 | 4.65k | ^ T1[LSB (text[1])] \ |
106 | 4.65k | ^ T2[LSB (text[2])] \ |
107 | 4.65k | ^ T3[LSB (text[3])] \ |
108 | 4.65k | ^ roundkey[3]; \ |
109 | 4.65k | } /* squareRound */ |
110 | | |
111 | 665 | #define squareFinal(text, temp, S, roundkey) \ |
112 | 665 | { \ |
113 | 665 | text[0] = ((word32) (S[MSB (temp[0])]) << 24) \ |
114 | 665 | ^ ((word32) (S[MSB (temp[1])]) << 16) \ |
115 | 665 | ^ ((word32) (S[MSB (temp[2])]) << 8) \ |
116 | 665 | ^ (word32) (S[MSB (temp[3])]) \ |
117 | 665 | ^ roundkey[0]; \ |
118 | 665 | text[1] = ((word32) (S[SSB (temp[0])]) << 24) \ |
119 | 665 | ^ ((word32) (S[SSB (temp[1])]) << 16) \ |
120 | 665 | ^ ((word32) (S[SSB (temp[2])]) << 8) \ |
121 | 665 | ^ (word32) (S[SSB (temp[3])]) \ |
122 | 665 | ^ roundkey[1]; \ |
123 | 665 | text[2] = ((word32) (S[TSB (temp[0])]) << 24) \ |
124 | 665 | ^ ((word32) (S[TSB (temp[1])]) << 16) \ |
125 | 665 | ^ ((word32) (S[TSB (temp[2])]) << 8) \ |
126 | 665 | ^ (word32) (S[TSB (temp[3])]) \ |
127 | 665 | ^ roundkey[2]; \ |
128 | 665 | text[3] = ((word32) (S[LSB (temp[0])]) << 24) \ |
129 | 665 | ^ ((word32) (S[LSB (temp[1])]) << 16) \ |
130 | 665 | ^ ((word32) (S[LSB (temp[2])]) << 8) \ |
131 | 665 | ^ (word32) (S[LSB (temp[3])]) \ |
132 | 665 | ^ roundkey[3]; \ |
133 | 665 | } /* squareFinal */ |
134 | | |
135 | | typedef BlockGetAndPut<word32, BigEndian> Block; |
136 | | |
137 | | void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
138 | 334 | { |
139 | 334 | word32 text[4], temp[4]; |
140 | 334 | Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); |
141 | | |
142 | | /* initial key addition */ |
143 | 334 | text[0] ^= roundkeys(0, 0); |
144 | 334 | text[1] ^= roundkeys(0, 1); |
145 | 334 | text[2] ^= roundkeys(0, 2); |
146 | 334 | text[3] ^= roundkeys(0, 3); |
147 | | |
148 | | /* ROUNDS - 1 full rounds */ |
149 | 1.33k | for (int i=1; i+1<ROUNDS; i+=2) |
150 | 1.00k | { |
151 | 1.00k | squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i)); |
152 | 1.00k | squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1)); |
153 | 1.00k | } |
154 | 334 | squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1)); |
155 | | |
156 | | /* last round (diffusion becomes only transposition) */ |
157 | 334 | squareFinal (text, temp, Se, roundkeys4(ROUNDS)); |
158 | | |
159 | 334 | Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); |
160 | 334 | } |
161 | | |
162 | | void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
163 | 331 | { |
164 | 331 | word32 text[4], temp[4]; |
165 | 331 | Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); |
166 | | |
167 | | /* initial key addition */ |
168 | 331 | text[0] ^= roundkeys(0, 0); |
169 | 331 | text[1] ^= roundkeys(0, 1); |
170 | 331 | text[2] ^= roundkeys(0, 2); |
171 | 331 | text[3] ^= roundkeys(0, 3); |
172 | | |
173 | | /* ROUNDS - 1 full rounds */ |
174 | 1.32k | for (int i=1; i+1<ROUNDS; i+=2) |
175 | 993 | { |
176 | 993 | squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i)); |
177 | 993 | squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1)); |
178 | 993 | } |
179 | 331 | squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1)); |
180 | | |
181 | | /* last round (diffusion becomes only transposition) */ |
182 | 331 | squareFinal (text, temp, Sd, roundkeys4(ROUNDS)); |
183 | | |
184 | 331 | Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); |
185 | 331 | } |
186 | | |
187 | | NAMESPACE_END |