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 9NAMESPACE_BEGIN(CryptoPP) 10 11// apply theta to a roundkey 12static 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 34void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) 35{ 36 AssertValidKeyLength(length); 37 38 static const word32 offset[ROUNDS] = { 39 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 40 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 41 }; 42 43 GetUserKey(BIG_ENDIAN_ORDER, roundkeys[0], KEYLENGTH/4, userKey, KEYLENGTH); 44 45 /* apply the key evolution function */ 46 for (int i = 1; i < ROUNDS+1; i++) 47 { 48 roundkeys[i][0] = roundkeys[i-1][0] ^ rotlFixed(roundkeys[i-1][3], 8U) ^ offset[i-1]; 49 roundkeys[i][1] = roundkeys[i-1][1] ^ roundkeys[i][0]; 50 roundkeys[i][2] = roundkeys[i-1][2] ^ roundkeys[i][1]; 51 roundkeys[i][3] = roundkeys[i-1][3] ^ roundkeys[i][2]; 52 } 53 54 /* produce the round keys */ 55 if (IsForwardTransformation()) 56 { 57 for (int i = 0; i < ROUNDS; i++) 58 SquareTransform (roundkeys[i], roundkeys[i]); 59 } 60 else 61 { 62 for (int i = 0; i < ROUNDS/2; i++) 63 for (int j = 0; j < 4; j++) 64 std::swap(roundkeys[i][j], roundkeys[ROUNDS-i][j]); 65 SquareTransform (roundkeys[ROUNDS], roundkeys[ROUNDS]); 66 } 67} 68 69#define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */ 70#define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */ 71#define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */ 72#define LSB(x) (((x) ) & 0xffU) /* least significant byte */ 73 74#define squareRound(text, temp, T0, T1, T2, T3, roundkey) \ 75{ \ 76 temp[0] = T0[MSB (text[0])] \ 77 ^ T1[MSB (text[1])] \ 78 ^ T2[MSB (text[2])] \ 79 ^ T3[MSB (text[3])] \ 80 ^ roundkey[0]; \ 81 temp[1] = T0[SSB (text[0])] \ 82 ^ T1[SSB (text[1])] \ 83 ^ T2[SSB (text[2])] \ 84 ^ T3[SSB (text[3])] \ 85 ^ roundkey[1]; \ 86 temp[2] = T0[TSB (text[0])] \ 87 ^ T1[TSB (text[1])] \ 88 ^ T2[TSB (text[2])] \ 89 ^ T3[TSB (text[3])] \ 90 ^ roundkey[2]; \ 91 temp[3] = T0[LSB (text[0])] \ 92 ^ T1[LSB (text[1])] \ 93 ^ T2[LSB (text[2])] \ 94 ^ T3[LSB (text[3])] \ 95 ^ roundkey[3]; \ 96} /* squareRound */ 97 98#define squareFinal(text, temp, S, roundkey) \ 99{ \ 100 text[0] = ((word32) (S[MSB (temp[0])]) << 24) \ 101 ^ ((word32) (S[MSB (temp[1])]) << 16) \ 102 ^ ((word32) (S[MSB (temp[2])]) << 8) \ 103 ^ (word32) (S[MSB (temp[3])]) \ 104 ^ roundkey[0]; \ 105 text[1] = ((word32) (S[SSB (temp[0])]) << 24) \ 106 ^ ((word32) (S[SSB (temp[1])]) << 16) \ 107 ^ ((word32) (S[SSB (temp[2])]) << 8) \ 108 ^ (word32) (S[SSB (temp[3])]) \ 109 ^ roundkey[1]; \ 110 text[2] = ((word32) (S[TSB (temp[0])]) << 24) \ 111 ^ ((word32) (S[TSB (temp[1])]) << 16) \ 112 ^ ((word32) (S[TSB (temp[2])]) << 8) \ 113 ^ (word32) (S[TSB (temp[3])]) \ 114 ^ roundkey[2]; \ 115 text[3] = ((word32) (S[LSB (temp[0])]) << 24) \ 116 ^ ((word32) (S[LSB (temp[1])]) << 16) \ 117 ^ ((word32) (S[LSB (temp[2])]) << 8) \ 118 ^ (word32) (S[LSB (temp[3])]) \ 119 ^ roundkey[3]; \ 120} /* squareFinal */ 121 122typedef BlockGetAndPut<word32, BigEndian> Block; 123 124void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 125{ 126 word32 text[4], temp[4]; 127 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); 128 129 /* initial key addition */ 130 text[0] ^= roundkeys[0][0]; 131 text[1] ^= roundkeys[0][1]; 132 text[2] ^= roundkeys[0][2]; 133 text[3] ^= roundkeys[0][3]; 134 135 /* ROUNDS - 1 full rounds */ 136 for (int i=1; i+1<ROUNDS; i+=2) 137 { 138 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys[i]); 139 squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys[i+1]); 140 } 141 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys[ROUNDS-1]); 142 143 /* last round (diffusion becomes only transposition) */ 144 squareFinal (text, temp, Se, roundkeys[ROUNDS]); 145 146 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); 147} 148 149void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 150{ 151 word32 text[4], temp[4]; 152 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); 153 154 /* initial key addition */ 155 text[0] ^= roundkeys[0][0]; 156 text[1] ^= roundkeys[0][1]; 157 text[2] ^= roundkeys[0][2]; 158 text[3] ^= roundkeys[0][3]; 159 160 /* ROUNDS - 1 full rounds */ 161 for (int i=1; i+1<ROUNDS; i+=2) 162 { 163 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys[i]); 164 squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys[i+1]); 165 } 166 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys[ROUNDS-1]); 167 168 /* last round (diffusion becomes only transposition) */ 169 squareFinal (text, temp, Sd, roundkeys[ROUNDS]); 170 171 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); 172} 173 174NAMESPACE_END 175