1 /* rijndael-alg-ref.c v2.0 August '99 2 * Reference ANSI C code 3 * authors: Paulo Barreto 4 * Vincent Rijmen, K.U.Leuven 5 * 6 * This code is placed in the public domain. 7 */ 8 9 #include "mvOs.h" 10 11 #include "mvAesAlg.h" 12 13 #include "mvAesBoxes.dat" 14 15 16 MV_U8 mul1(MV_U8 aa, MV_U8 bb); 17 void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC); 18 void ShiftRow128Enc(MV_U8 a[4][MAXBC]); 19 void ShiftRow128Dec(MV_U8 a[4][MAXBC]); 20 void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]); 21 void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]); 22 void InvMixColumn(MV_U8 a[4][MAXBC]); 23 24 25 #define mul(aa, bb) (mask[bb] & Alogtable[aa + Logtable[bb]]) 26 27 MV_U8 mul1(MV_U8 aa, MV_U8 bb) 28 { 29 return mask[bb] & Alogtable[aa + Logtable[bb]]; 30 } 31 32 33 void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC) 34 { 35 /* Exor corresponding text input and round key input bytes 36 */ 37 ((MV_U32*)(&(a[0][0])))[0] ^= ((MV_U32*)(&(rk[0][0])))[0]; 38 ((MV_U32*)(&(a[1][0])))[0] ^= ((MV_U32*)(&(rk[1][0])))[0]; 39 ((MV_U32*)(&(a[2][0])))[0] ^= ((MV_U32*)(&(rk[2][0])))[0]; 40 ((MV_U32*)(&(a[3][0])))[0] ^= ((MV_U32*)(&(rk[3][0])))[0]; 41 42 } 43 44 void ShiftRow128Enc(MV_U8 a[4][MAXBC]) { 45 /* Row 0 remains unchanged 46 * The other three rows are shifted a variable amount 47 */ 48 MV_U8 tmp[MAXBC]; 49 50 tmp[0] = a[1][1]; 51 tmp[1] = a[1][2]; 52 tmp[2] = a[1][3]; 53 tmp[3] = a[1][0]; 54 55 ((MV_U32*)(&(a[1][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 56 /* 57 a[1][0] = tmp[0]; 58 a[1][1] = tmp[1]; 59 a[1][2] = tmp[2]; 60 a[1][3] = tmp[3]; 61 */ 62 tmp[0] = a[2][2]; 63 tmp[1] = a[2][3]; 64 tmp[2] = a[2][0]; 65 tmp[3] = a[2][1]; 66 67 ((MV_U32*)(&(a[2][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 68 /* 69 a[2][0] = tmp[0]; 70 a[2][1] = tmp[1]; 71 a[2][2] = tmp[2]; 72 a[2][3] = tmp[3]; 73 */ 74 tmp[0] = a[3][3]; 75 tmp[1] = a[3][0]; 76 tmp[2] = a[3][1]; 77 tmp[3] = a[3][2]; 78 79 ((MV_U32*)(&(a[3][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 80 /* 81 a[3][0] = tmp[0]; 82 a[3][1] = tmp[1]; 83 a[3][2] = tmp[2]; 84 a[3][3] = tmp[3]; 85 */ 86 } 87 88 void ShiftRow128Dec(MV_U8 a[4][MAXBC]) { 89 /* Row 0 remains unchanged 90 * The other three rows are shifted a variable amount 91 */ 92 MV_U8 tmp[MAXBC]; 93 94 tmp[0] = a[1][3]; 95 tmp[1] = a[1][0]; 96 tmp[2] = a[1][1]; 97 tmp[3] = a[1][2]; 98 99 ((MV_U32*)(&(a[1][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 100 /* 101 a[1][0] = tmp[0]; 102 a[1][1] = tmp[1]; 103 a[1][2] = tmp[2]; 104 a[1][3] = tmp[3]; 105 */ 106 107 tmp[0] = a[2][2]; 108 tmp[1] = a[2][3]; 109 tmp[2] = a[2][0]; 110 tmp[3] = a[2][1]; 111 112 ((MV_U32*)(&(a[2][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 113 /* 114 a[2][0] = tmp[0]; 115 a[2][1] = tmp[1]; 116 a[2][2] = tmp[2]; 117 a[2][3] = tmp[3]; 118 */ 119 120 tmp[0] = a[3][1]; 121 tmp[1] = a[3][2]; 122 tmp[2] = a[3][3]; 123 tmp[3] = a[3][0]; 124 125 ((MV_U32*)(&(a[3][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; 126 /* 127 a[3][0] = tmp[0]; 128 a[3][1] = tmp[1]; 129 a[3][2] = tmp[2]; 130 a[3][3] = tmp[3]; 131 */ 132 } 133 134 void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]) { 135 /* Replace every byte of the input by the byte at that place 136 * in the nonlinear S-box 137 */ 138 int i, j; 139 140 for(i = 0; i < 4; i++) 141 for(j = 0; j < 4; j++) a[i][j] = box[a[i][j]] ; 142 } 143 144 void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]) { 145 /* Mix the four bytes of every column in a linear way 146 */ 147 MV_U8 b[4][MAXBC]; 148 int i, j; 149 150 for(j = 0; j < 4; j++){ 151 b[0][j] = mul(25,a[0][j]) ^ mul(1,a[1][j]) ^ a[2][j] ^ a[3][j]; 152 b[1][j] = mul(25,a[1][j]) ^ mul(1,a[2][j]) ^ a[3][j] ^ a[0][j]; 153 b[2][j] = mul(25,a[2][j]) ^ mul(1,a[3][j]) ^ a[0][j] ^ a[1][j]; 154 b[3][j] = mul(25,a[3][j]) ^ mul(1,a[0][j]) ^ a[1][j] ^ a[2][j]; 155 } 156 for(i = 0; i < 4; i++) 157 /*for(j = 0; j < BC; j++) a[i][j] = b[i][j];*/ 158 ((MV_U32*)(&(a[i][0])))[0] = ((MV_U32*)(&(b[i][0])))[0] ^ ((MV_U32*)(&(rk[i][0])))[0]; 159 } 160 161 void InvMixColumn(MV_U8 a[4][MAXBC]) { 162 /* Mix the four bytes of every column in a linear way 163 * This is the opposite operation of Mixcolumn 164 */ 165 MV_U8 b[4][MAXBC]; 166 int i, j; 167 168 for(j = 0; j < 4; j++){ 169 b[0][j] = mul(223,a[0][j]) ^ mul(104,a[1][j]) ^ mul(238,a[2][j]) ^ mul(199,a[3][j]); 170 b[1][j] = mul(223,a[1][j]) ^ mul(104,a[2][j]) ^ mul(238,a[3][j]) ^ mul(199,a[0][j]); 171 b[2][j] = mul(223,a[2][j]) ^ mul(104,a[3][j]) ^ mul(238,a[0][j]) ^ mul(199,a[1][j]); 172 b[3][j] = mul(223,a[3][j]) ^ mul(104,a[0][j]) ^ mul(238,a[1][j]) ^ mul(199,a[2][j]); 173 } 174 for(i = 0; i < 4; i++) 175 /*for(j = 0; j < BC; j++) a[i][j] = b[i][j];*/ 176 ((MV_U32*)(&(a[i][0])))[0] = ((MV_U32*)(&(b[i][0])))[0]; 177 } 178 179 int rijndaelKeySched (MV_U8 k[4][MAXKC], int keyBits, int blockBits, MV_U8 W[MAXROUNDS+1][4][MAXBC]) 180 { 181 /* Calculate the necessary round keys 182 * The number of calculations depends on keyBits and blockBits 183 */ 184 int KC, BC, ROUNDS; 185 int i, j, t, rconpointer = 0; 186 MV_U8 tk[4][MAXKC]; 187 188 switch (keyBits) { 189 case 128: KC = 4; break; 190 case 192: KC = 6; break; 191 case 256: KC = 8; break; 192 default : return (-1); 193 } 194 195 switch (blockBits) { 196 case 128: BC = 4; break; 197 case 192: BC = 6; break; 198 case 256: BC = 8; break; 199 default : return (-2); 200 } 201 202 switch (keyBits >= blockBits ? keyBits : blockBits) { 203 case 128: ROUNDS = 10; break; 204 case 192: ROUNDS = 12; break; 205 case 256: ROUNDS = 14; break; 206 default : return (-3); /* this cannot happen */ 207 } 208 209 210 for(j = 0; j < KC; j++) 211 for(i = 0; i < 4; i++) 212 tk[i][j] = k[i][j]; 213 t = 0; 214 /* copy values into round key array */ 215 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) 216 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; 217 218 while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ 219 /* calculate new values */ 220 for(i = 0; i < 4; i++) 221 tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; 222 tk[0][0] ^= rcon[rconpointer++]; 223 224 if (KC != 8) 225 for(j = 1; j < KC; j++) 226 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 227 else { 228 for(j = 1; j < KC/2; j++) 229 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 230 for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; 231 for(j = KC/2 + 1; j < KC; j++) 232 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 233 } 234 /* copy values into round key array */ 235 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) 236 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; 237 } 238 239 return 0; 240 } 241 242 243 244 int rijndaelEncrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds) 245 { 246 /* Encryption of one block. 247 */ 248 int r, BC, ROUNDS; 249 250 BC = 4; 251 ROUNDS = rounds; 252 253 /* begin with a key addition 254 */ 255 256 KeyAddition(a,rk[0],BC); 257 258 /* ROUNDS-1 ordinary rounds 259 */ 260 for(r = 1; r < ROUNDS; r++) { 261 Substitution(a,S); 262 ShiftRow128Enc(a); 263 MixColumn(a, rk[r]); 264 /*KeyAddition(a,rk[r],BC);*/ 265 } 266 267 /* Last round is special: there is no MixColumn 268 */ 269 Substitution(a,S); 270 ShiftRow128Enc(a); 271 KeyAddition(a,rk[ROUNDS],BC); 272 273 return 0; 274 } 275 276 277 int rijndaelDecrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds) 278 { 279 int r, BC, ROUNDS; 280 281 BC = 4; 282 ROUNDS = rounds; 283 284 /* To decrypt: apply the inverse operations of the encrypt routine, 285 * in opposite order 286 * 287 * (KeyAddition is an involution: it 's equal to its inverse) 288 * (the inverse of Substitution with table S is Substitution with the inverse table of S) 289 * (the inverse of Shiftrow is Shiftrow over a suitable distance) 290 */ 291 292 /* First the special round: 293 * without InvMixColumn 294 * with extra KeyAddition 295 */ 296 KeyAddition(a,rk[ROUNDS],BC); 297 ShiftRow128Dec(a); 298 Substitution(a,Si); 299 300 /* ROUNDS-1 ordinary rounds 301 */ 302 for(r = ROUNDS-1; r > 0; r--) { 303 KeyAddition(a,rk[r],BC); 304 InvMixColumn(a); 305 ShiftRow128Dec(a); 306 Substitution(a,Si); 307 308 } 309 310 /* End with the extra key addition 311 */ 312 313 KeyAddition(a,rk[0],BC); 314 315 return 0; 316 } 317 318