Crypto++  8.8
Free C++ class library of cryptographic schemes
square.cpp
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 {
24  static const byte G[4][4] =
25  {
26  {0x02U, 0x01U, 0x01U, 0x03U},
27  {0x03U, 0x02U, 0x01U, 0x01U},
28  {0x01U, 0x03U, 0x02U, 0x01U},
29  {0x01U, 0x01U, 0x03U, 0x02U}
30  };
31 
32  GF256 gf256(0xf5);
33 
34  for (int i = 0; i < 4; i++)
35  {
36  word32 temp = 0;
37  for (unsigned int j = 0; j < 4; j++)
38  for (unsigned int k = 0; k < 4; k++)
39  temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8);
40  out[i] = temp;
41  }
42 }
43 
44 #define roundkeys(i, j) m_roundkeys[(i)*4+(j)]
45 #define roundkeys4(i) (m_roundkeys+(i)*4)
46 
47 void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
48 {
49  AssertValidKeyLength(length);
50 
51  static const word32 offset[ROUNDS] = {
52  0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
53  0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
54  };
55 
56  GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH);
57 
58  /* apply the key evolution function */
59  for (int i = 1; i < ROUNDS+1; i++)
60  {
61  roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlConstant<8>(roundkeys(i-1, 3)) ^ offset[i-1];
62  roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0);
63  roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1);
64  roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2);
65  }
66 
67  /* produce the round keys */
68  if (IsForwardTransformation())
69  {
70  for (int i = 0; i < ROUNDS; i++)
71  SquareTransform (roundkeys4(i), roundkeys4(i));
72  }
73  else
74  {
75  for (int i = 0; i < ROUNDS/2; i++)
76  for (int j = 0; j < 4; j++)
77  std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j));
78  SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS));
79  }
80 }
81 
82 #define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */
83 #define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */
84 #define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */
85 #define LSB(x) (((x) ) & 0xffU) /* least significant byte */
86 
87 #define squareRound(text, temp, T0, T1, T2, T3, roundkey) \
88 { \
89  temp[0] = T0[MSB (text[0])] \
90  ^ T1[MSB (text[1])] \
91  ^ T2[MSB (text[2])] \
92  ^ T3[MSB (text[3])] \
93  ^ roundkey[0]; \
94  temp[1] = T0[SSB (text[0])] \
95  ^ T1[SSB (text[1])] \
96  ^ T2[SSB (text[2])] \
97  ^ T3[SSB (text[3])] \
98  ^ roundkey[1]; \
99  temp[2] = T0[TSB (text[0])] \
100  ^ T1[TSB (text[1])] \
101  ^ T2[TSB (text[2])] \
102  ^ T3[TSB (text[3])] \
103  ^ roundkey[2]; \
104  temp[3] = T0[LSB (text[0])] \
105  ^ T1[LSB (text[1])] \
106  ^ T2[LSB (text[2])] \
107  ^ T3[LSB (text[3])] \
108  ^ roundkey[3]; \
109 } /* squareRound */
110 
111 #define squareFinal(text, temp, S, roundkey) \
112 { \
113  text[0] = ((word32) (S[MSB (temp[0])]) << 24) \
114  ^ ((word32) (S[MSB (temp[1])]) << 16) \
115  ^ ((word32) (S[MSB (temp[2])]) << 8) \
116  ^ (word32) (S[MSB (temp[3])]) \
117  ^ roundkey[0]; \
118  text[1] = ((word32) (S[SSB (temp[0])]) << 24) \
119  ^ ((word32) (S[SSB (temp[1])]) << 16) \
120  ^ ((word32) (S[SSB (temp[2])]) << 8) \
121  ^ (word32) (S[SSB (temp[3])]) \
122  ^ roundkey[1]; \
123  text[2] = ((word32) (S[TSB (temp[0])]) << 24) \
124  ^ ((word32) (S[TSB (temp[1])]) << 16) \
125  ^ ((word32) (S[TSB (temp[2])]) << 8) \
126  ^ (word32) (S[TSB (temp[3])]) \
127  ^ roundkey[2]; \
128  text[3] = ((word32) (S[LSB (temp[0])]) << 24) \
129  ^ ((word32) (S[LSB (temp[1])]) << 16) \
130  ^ ((word32) (S[LSB (temp[2])]) << 8) \
131  ^ (word32) (S[LSB (temp[3])]) \
132  ^ roundkey[3]; \
133 } /* squareFinal */
134 
136 
137 void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
138 {
139  word32 text[4], temp[4];
140  Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
141 
142  /* initial key addition */
143  text[0] ^= roundkeys(0, 0);
144  text[1] ^= roundkeys(0, 1);
145  text[2] ^= roundkeys(0, 2);
146  text[3] ^= roundkeys(0, 3);
147 
148  /* ROUNDS - 1 full rounds */
149  for (int i=1; i+1<ROUNDS; i+=2)
150  {
151  squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i));
152  squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1));
153  }
154  squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1));
155 
156  /* last round (diffusion becomes only transposition) */
157  squareFinal (text, temp, Se, roundkeys4(ROUNDS));
158 
159  Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
160 }
161 
162 void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
163 {
164  word32 text[4], temp[4];
165  Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
166 
167  /* initial key addition */
168  text[0] ^= roundkeys(0, 0);
169  text[1] ^= roundkeys(0, 1);
170  text[2] ^= roundkeys(0, 2);
171  text[3] ^= roundkeys(0, 3);
172 
173  /* ROUNDS - 1 full rounds */
174  for (int i=1; i+1<ROUNDS; i+=2)
175  {
176  squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i));
177  squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1));
178  }
179  squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1));
180 
181  /* last round (diffusion becomes only transposition) */
182  squareFinal (text, temp, Sd, roundkeys4(ROUNDS));
183 
184  Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
185 }
186 
187 NAMESPACE_END
GF(256) with polynomial basis.
Definition: gf256.h:16
Interface for retrieving values given their names.
Definition: cryptlib.h:327
Access a block of memory.
Definition: misc.h:3016
Library configuration file.
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:152
Classes and functions for schemes over GF(256)
Utility functions for the Crypto++ library.
void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
Copy bytes in a buffer to an array of elements in big-endian order.
Definition: misc.h:2500
Crypto++ library namespace.
Precompiled header file.
void swap(::SecBlock< T, A > &a, ::SecBlock< T, A > &b)
Swap two SecBlocks.
Definition: secblock.h:1289
Classes for the Square block cipher.
Access a block of memory.
Definition: misc.h:3053