1/* rijndael-alg-ref.c v2.0 August '99 2 * Reference ANSI C code 3 * authors: Paulo Barreto 4 * Vincent Rijmen 5 */ 6 7#include <stdio.h> 8#include <stdlib.h> 9 10#include "rijndael-alg-ref.h" 11 12#define SC ((BC - 4) >> 1) 13 14#include "boxes-ref.h" 15 16static const word8 shifts[3][4][2] = { 17 { { 0, 0 }, 18 { 1, 3 }, 19 { 2, 2 }, 20 { 3, 1 } 21 }, 22 { { 0, 0 }, 23 { 1, 5 }, 24 { 2, 4 }, 25 { 3, 3 } 26 }, 27 { { 0, 0 }, 28 { 1, 7 }, 29 { 3, 5 }, 30 { 4, 4 } 31 } 32}; 33 34 35static word8 mul(word8 a, word8 b) { 36 /* multiply two elements of GF(2^m) 37 * needed for MixColumn and InvMixColumn 38 */ 39 if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255]; 40 else return 0; 41} 42 43static void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) { 44 /* Exor corresponding text input and round key input bytes 45 */ 46 int i, j; 47 48 for(i = 0; i < 4; i++) 49 for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j]; 50} 51 52static void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) { 53 /* Row 0 remains unchanged 54 * The other three rows are shifted a variable amount 55 */ 56 word8 tmp[MAXBC]; 57 int i, j; 58 59 for(i = 1; i < 4; i++) { 60 for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC]; 61 for(j = 0; j < BC; j++) a[i][j] = tmp[j]; 62 } 63} 64 65static void Substitution(word8 a[4][MAXBC], const word8 box[256], word8 BC) { 66 /* Replace every byte of the input by the byte at that place 67 * in the nonlinear S-box 68 */ 69 int i, j; 70 71 for(i = 0; i < 4; i++) 72 for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ; 73} 74 75static void MixColumn(word8 a[4][MAXBC], word8 BC) { 76 /* Mix the four bytes of every column in a linear way 77 */ 78 word8 b[4][MAXBC]; 79 int i, j; 80 81 for(j = 0; j < BC; j++) 82 for(i = 0; i < 4; i++) 83 b[i][j] = mul(2,a[i][j]) 84 ^ mul(3,a[(i + 1) % 4][j]) 85 ^ a[(i + 2) % 4][j] 86 ^ a[(i + 3) % 4][j]; 87 for(i = 0; i < 4; i++) 88 for(j = 0; j < BC; j++) a[i][j] = b[i][j]; 89} 90 91static void InvMixColumn(word8 a[4][MAXBC], word8 BC) { 92 /* Mix the four bytes of every column in a linear way 93 * This is the opposite operation of Mixcolumn 94 */ 95 word8 b[4][MAXBC]; 96 int i, j; 97 98 for(j = 0; j < BC; j++) 99 for(i = 0; i < 4; i++) 100 b[i][j] = mul(0xe,a[i][j]) 101 ^ mul(0xb,a[(i + 1) % 4][j]) 102 ^ mul(0xd,a[(i + 2) % 4][j]) 103 ^ mul(0x9,a[(i + 3) % 4][j]); 104 for(i = 0; i < 4; i++) 105 for(j = 0; j < BC; j++) a[i][j] = b[i][j]; 106} 107 108int _rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, word8 W[MAXROUNDS+1][4][MAXBC]) { 109 /* Calculate the necessary round keys 110 * The number of calculations depends on keyBits and blockBits 111 */ 112 int KC, BC, ROUNDS; 113 int i, j, t, rconpointer = 0; 114 word8 tk[4][MAXKC]; 115 116 switch (keyBits) { 117 case 128: KC = 4; break; 118 case 192: KC = 6; break; 119 case 256: KC = 8; break; 120 default : return (-1); 121 } 122 123 switch (blockBits) { 124 case 128: BC = 4; break; 125 case 192: BC = 6; break; 126 case 256: BC = 8; break; 127 default : return (-2); 128 } 129 130 switch (keyBits >= blockBits ? keyBits : blockBits) { 131 case 128: ROUNDS = 10; break; 132 case 192: ROUNDS = 12; break; 133 case 256: ROUNDS = 14; break; 134 default : return (-3); /* this cannot happen */ 135 } 136 137 138 for(j = 0; j < KC; j++) 139 for(i = 0; i < 4; i++) 140 tk[i][j] = k[i][j]; 141 t = 0; 142 /* copy values into round key array */ 143 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) 144 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; 145 146 while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ 147 /* calculate new values */ 148 for(i = 0; i < 4; i++) 149 tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; 150 tk[0][0] ^= rcon[rconpointer++]; 151 152 if (KC != 8) 153 for(j = 1; j < KC; j++) 154 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 155 else { 156 for(j = 1; j < KC/2; j++) 157 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 158 for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; 159 for(j = KC/2 + 1; j < KC; j++) 160 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; 161 } 162 /* copy values into round key array */ 163 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) 164 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; 165 } 166 167 return 0; 168} 169 170int _rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC]) 171{ 172 /* Encryption of one block. 173 */ 174 int r, BC, ROUNDS; 175 176 switch (blockBits) { 177 case 128: BC = 4; break; 178 case 192: BC = 6; break; 179 case 256: BC = 8; break; 180 default : return (-2); 181 } 182 183 switch (keyBits >= blockBits ? keyBits : blockBits) { 184 case 128: ROUNDS = 10; break; 185 case 192: ROUNDS = 12; break; 186 case 256: ROUNDS = 14; break; 187 default : return (-3); /* this cannot happen */ 188 } 189 190 /* begin with a key addition 191 */ 192 KeyAddition(a,rk[0],BC); 193 194 /* ROUNDS-1 ordinary rounds 195 */ 196 for(r = 1; r < ROUNDS; r++) { 197 Substitution(a,S,BC); 198 ShiftRow(a,0,BC); 199 MixColumn(a,BC); 200 KeyAddition(a,rk[r],BC); 201 } 202 203 /* Last round is special: there is no MixColumn 204 */ 205 Substitution(a,S,BC); 206 ShiftRow(a,0,BC); 207 KeyAddition(a,rk[ROUNDS],BC); 208 209 return 0; 210} 211 212 213#ifndef __APPLE__ 214 215int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, 216 word8 rk[MAXROUNDS+1][4][MAXBC], int rounds) 217/* Encrypt only a certain number of rounds. 218 * Only used in the Intermediate Value Known Answer Test. 219 */ 220{ 221 int r, BC, ROUNDS; 222 223 switch (blockBits) { 224 case 128: BC = 4; break; 225 case 192: BC = 6; break; 226 case 256: BC = 8; break; 227 default : return (-2); 228 } 229 230 switch (keyBits >= blockBits ? keyBits : blockBits) { 231 case 128: ROUNDS = 10; break; 232 case 192: ROUNDS = 12; break; 233 case 256: ROUNDS = 14; break; 234 default : return (-3); /* this cannot happen */ 235 } 236 237 /* make number of rounds sane */ 238 if (rounds > ROUNDS) rounds = ROUNDS; 239 240 /* begin with a key addition 241 */ 242 KeyAddition(a,rk[0],BC); 243 244 /* at most ROUNDS-1 ordinary rounds 245 */ 246 for(r = 1; (r <= rounds) && (r < ROUNDS); r++) { 247 Substitution(a,S,BC); 248 ShiftRow(a,0,BC); 249 MixColumn(a,BC); 250 KeyAddition(a,rk[r],BC); 251 } 252 253 /* if necessary, do the last, special, round: 254 */ 255 if (rounds == ROUNDS) { 256 Substitution(a,S,BC); 257 ShiftRow(a,0,BC); 258 KeyAddition(a,rk[ROUNDS],BC); 259 } 260 261 return 0; 262} 263#endif /* __APPLE__ */ 264 265int _rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC]) 266{ 267 int r, BC, ROUNDS; 268 269 switch (blockBits) { 270 case 128: BC = 4; break; 271 case 192: BC = 6; break; 272 case 256: BC = 8; break; 273 default : return (-2); 274 } 275 276 switch (keyBits >= blockBits ? keyBits : blockBits) { 277 case 128: ROUNDS = 10; break; 278 case 192: ROUNDS = 12; break; 279 case 256: ROUNDS = 14; break; 280 default : return (-3); /* this cannot happen */ 281 } 282 283 /* To decrypt: apply the inverse operations of the encrypt routine, 284 * in opposite order 285 * 286 * (KeyAddition is an involution: it 's equal to its inverse) 287 * (the inverse of Substitution with table S is Substitution with the inverse table of S) 288 * (the inverse of Shiftrow is Shiftrow over a suitable distance) 289 */ 290 291 /* First the special round: 292 * without InvMixColumn 293 * with extra KeyAddition 294 */ 295 KeyAddition(a,rk[ROUNDS],BC); 296 Substitution(a,Si,BC); 297 ShiftRow(a,1,BC); 298 299 /* ROUNDS-1 ordinary rounds 300 */ 301 for(r = ROUNDS-1; r > 0; r--) { 302 KeyAddition(a,rk[r],BC); 303 InvMixColumn(a,BC); 304 Substitution(a,Si,BC); 305 ShiftRow(a,1,BC); 306 } 307 308 /* End with the extra key addition 309 */ 310 311 KeyAddition(a,rk[0],BC); 312 313 return 0; 314} 315 316#ifndef __APPLE__ 317 318int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, 319 word8 rk[MAXROUNDS+1][4][MAXBC], int rounds) 320/* Decrypt only a certain number of rounds. 321 * Only used in the Intermediate Value Known Answer Test. 322 * Operations rearranged such that the intermediate values 323 * of decryption correspond with the intermediate values 324 * of encryption. 325 */ 326{ 327 int r, BC, ROUNDS; 328 329 switch (blockBits) { 330 case 128: BC = 4; break; 331 case 192: BC = 6; break; 332 case 256: BC = 8; break; 333 default : return (-2); 334 } 335 336 switch (keyBits >= blockBits ? keyBits : blockBits) { 337 case 128: ROUNDS = 10; break; 338 case 192: ROUNDS = 12; break; 339 case 256: ROUNDS = 14; break; 340 default : return (-3); /* this cannot happen */ 341 } 342 343 344 /* make number of rounds sane */ 345 if (rounds > ROUNDS) rounds = ROUNDS; 346 347 /* First the special round: 348 * without InvMixColumn 349 * with extra KeyAddition 350 */ 351 KeyAddition(a,rk[ROUNDS],BC); 352 Substitution(a,Si,BC); 353 ShiftRow(a,1,BC); 354 355 /* ROUNDS-1 ordinary rounds 356 */ 357 for(r = ROUNDS-1; r > rounds; r--) { 358 KeyAddition(a,rk[r],BC); 359 InvMixColumn(a,BC); 360 Substitution(a,Si,BC); 361 ShiftRow(a,1,BC); 362 } 363 364 if (rounds == 0) { 365 /* End with the extra key addition 366 */ 367 KeyAddition(a,rk[0],BC); 368 } 369 370 return 0; 371} 372 373#endif /* __APPLE__ */ 374