1 // Rijndael
  2 // John Bryan, 2004
  3 
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 
  7 
  8 #define byte unsigned char
  9 
 10 
 11 byte Logtable[256] = {
 12   0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238, 223,   3,
 13 100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200, 248, 105,  28, 193,
 14 125, 194,  29, 181, 249, 185,  39, 106,  77, 228, 166, 114, 154, 201,   9, 120,
 15 101,  47, 138,   5,  33,  15, 225,  36,  18, 240, 130,  69,  53, 147, 218, 142,
 16 150, 143, 219, 189,  54, 208, 206, 148,  19,  92, 210, 241,  64,  70, 131,  56,
 17 102, 221, 253,  48, 191,   6, 139,  98, 179,  37, 226, 152,  34, 136, 145,  16,
 18 126, 110,  72, 195, 163, 182,  30,  66,  58, 107,  40,  84, 250, 133,  61, 186,
 19  43, 121,  10,  21, 155, 159,  94, 202,  78, 212, 172, 229, 243, 115, 167,  87,
 20 175,  88, 168,  80, 244, 234, 214, 116,  79, 174, 233, 213, 231, 230, 173, 232,
 21  44, 215, 117, 122, 235,  22,  11, 245,  89, 203,  95, 176, 156, 169,  81, 160,
 22 127,  12, 246, 111,  23, 196,  73, 236, 216,  67,  31,  45, 164, 118, 123, 183,
 23 204, 187,  62,  90, 251,  96, 177, 134,  59,  82, 161, 108, 170,  85,  41, 157,
 24 151, 178, 135, 144,  97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209,
 25  83,  57, 132,  60,  65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171,
 26  68,  17, 146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153, 227, 165,
 27 103,  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128, 192, 247, 112,   7,
 28 };
 29 
 30 
 31 byte Alogtable[256] = {
 32   1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,  19,  53,
 33  95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,  30,  34, 102, 170,
 34 229,  52,  92, 228,  55,  89, 235,  38, 106, 190, 217, 112, 144, 171, 230,  49,
 35  83, 245,   4,  12,  20,  60,  68, 204,  79, 209, 104, 184, 211, 110, 178, 205,
 36  76, 212, 103, 169, 224,  59,  77, 215,  98, 166, 241,   8,  24,  40, 120, 136,
 37 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154,
 38 181, 196,  87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
 39 254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,  96, 160,
 40 251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86, 250,  21,  63,  65,
 41 195,  94, 226,  61,  71, 201,  64, 192,  91, 237,  44, 116, 156, 191, 218, 117,
 42 159, 186, 213, 100, 172, 239,  42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
 43 155, 182, 193,  88, 232,  35, 101, 175, 234,  37, 111, 177, 200,  67, 197,  84,
 44 252,  31,  33,  99, 165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,
 45  69, 207,  74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
 46  18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,  13,  23,
 47  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180, 199,  82, 246,   1,
 48 };
 49 
 50 
 51 byte S[256] = {
 52  99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 118,
 53 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
 54 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 216,  49,  21,
 55   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,
 56   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,  47, 132,
 57  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207,
 58 208, 239, 170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
 59  81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210,
 60 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25, 115,
 61  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20, 222,  94,  11, 219,
 62 224,  50,  58,  10,  73,   6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121,
 63 231, 200,  55, 109, 141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8,
 64 186, 120,  37,  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
 65 112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
 66 225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
 67 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  22,
 68 };
 69 
 70 
 71 byte Si[256] = {
 72  82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 251,
 73 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 233, 203,
 74  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 250, 195,  78,
 75   8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37,
 76 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101, 182, 146,
 77 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132,
 78 144, 216, 171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6,
 79 208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,
 80  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
 81 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,  28, 117, 223, 110,
 82  71, 241,  26, 113,  29,  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27,
 83 252,  86,  62,  75, 198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,
 84  31, 221, 168,  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
 85  96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239,
 86 160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97,
 87  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12, 125,
 88 };
 89 
 90 byte iG[4][4] = {
 91 0x0e, 0x09, 0x0d, 0x0b,
 92 0x0b, 0x0e, 0x09, 0x0d,
 93 0x0d, 0x0b, 0x0e, 0x09,
 94 0x09, 0x0d, 0x0b, 0x0e,
 95 };
 96 
 97 byte RC[11] = { 0x00,0x01,0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36} ;
 98 
 99 
100 static byte shifts [4][2] = {
101    0, 0,
102    1, 3,
103    2, 2,
104    3, 1
105 };
106 
107 void SetPlaintext(byte P[4][4]);
108 void SetKey(byte K[4][4]);
109 void KeyExpansion (byte K[4][4], byte round_keyi[11][4][4]);
110 void Encrypt (byte a[4][4], byte round_key[11][4][4]);
111 void AddRoundKey(byte a[4][4], byte rk[4][4]);
112 void SubBytes (byte a[4][4], byte box[256]);
113 void ShiftRows(byte a[4][4], byte d);
114 byte Mul(byte c, byte d);
115 void MixColumns(byte a[4][4]);
116 void PrintFunction(byte a[4][4], byte r, char b[6]);
117 void PrintRoundKey(byte round_key[11][4][4], byte r);
118 int Decrypt (byte a[4][4], byte round_keyk[11][4][4]);
119 void InvMixColumns(byte a[4][4]);
120 
121 byte P[4][4];
122 byte K[4][4];
123 
124 main() {
125    int i,j,k;
126    byte P[4][4];
127    byte W[4][44];
128    byte round_key[11][4][4];
129    SetPlaintext(P);
130    SetKey(K);
131    KeyExpansion (K,round_key);
132    Encrypt (P,round_key);
133    Decrypt (P,round_key);
134 }
135 
136 
137 void SetPlaintext(byte P[4][4]){
138          P[0][0]=0x32;
139          P[1][0]=0x43;
140          P[2][0]=0xf6;
141          P[3][0]=0xa8;
142          P[0][1]=0x88;
143          P[1][1]=0x5a;
144          P[2][1]=0x30;
145          P[3][1]=0x8d;
146          P[0][2]=0x31;
147          P[1][2]=0x31;
148          P[2][2]=0x98;
149          P[3][2]=0xa2;
150          P[0][3]=0xe0;
151          P[1][3]=0x37;
152          P[2][3]=0x07;
153          P[3][3]=0x34;
154 }
155 
156 
157 void SetKey(byte K[4][4]){
158          K[0][0]=0x2b;
159          K[1][0]=0x7e;
160          K[2][0]=0x15;
161          K[3][0]=0x16;
162          K[0][1]=0x28;
163          K[1][1]=0xae;
164          K[2][1]=0xd2;
165          K[3][1]=0xa6;
166          K[0][2]=0xab;
167          K[1][2]=0xf7;
168          K[2][2]=0x15;
169          K[3][2]=0x88;
170          K[0][3]=0x09;
171          K[1][3]=0xcf;
172          K[2][3]=0x4f;
173          K[3][3]=0x3c;
174 }
175 
176 
177 void KeyExpansion (byte   K[4][4],
178                   byte   round_key[11][4][4]) {
179         /* Calculate the necessary round keys */
180         int i, j, k, m, u, v, w;
181         byte key[11][16];
182         byte W[4][44];
183 
184         for(j = 0; j < 4; j++)
185                 for(i = 0; i < 4; i++)
186                         W[i][j] = K[i][j];
187         for(j = 4; j < 44; j++)
188             {
189             if (j%4 == 0)
190                {
191                W[0][j] = W[0][j-4] ^ S[W[1][j-1]] ^ RC[j/4];
192                for(i = 1; i < 4; i++)
193                    W[i][j] = W[i][j-4] ^ S[W[(i+1)%4][j-1]];
194                }
195             else
196                {
197                for(i = 0; i < 4; i++)
198                    W[i][j] = W[i][j-4] ^ W[i][j-1];
199                }
200             }
201          /* copy values into round key array */
202 
203      printf("The key schedule:\n \n");
204      for (k=0; k<=10; k++)
205      {
206          printf("R[%02d].key_schedule    ",k);
207          m=0;
208          for (j=(4*k); j<=(4*(k+1))-1; j++)
209          {
210             for (i=0; i<=3; i++)
211             {
212             printf("%02x",W[i][j]);
213             key[k][m]=W[i][j];
214             m++;
215             }
216          }
217          printf("\n");
218      }
219      for (u=0; u<=10; u++)
220         for (v=4*u; v<=4*u+3; v++)
221             for (w=0; w<=3; w++)
222                round_key[u][w][v%4]=W[w][v];
223      printf("\nThe key schedule in 11x4x4 matrix format:\n \n");
224      for (u=0; u<=10; u++)
225         {
226         for (w=0; w<=3; w++)
227            {
228            for (v=0; v<=3; v++)
229               {
230               printf("%02x  ", round_key[u][w][v]);
231               }
232               printf("\n");
233            }
234         printf("\n");
235         printf("\n");
236         }
237 }
238 
239 
240 void Encrypt (byte a[4][4], byte round_key[11][4][4])
241 {
242         /* Encryption of one block.  */
243         int r;
244         printf("\n    Encryption\n");
245         printf("legend - round r = 0 to 10:\n");
246         printf("input:  plaintext input\n");
247         printf("start:  state at start of round[r]\n");
248         printf("s_box:  state after s_box substitution\n");
249         printf("s_row:  state after shift row transformation\n");
250         printf("m_col:  state after mix column transformation\n");
251         printf("k_sch:  key schedule value for round[r]\n");
252         printf("output: ciphertext output\n\n");
253         PrintFunction(a,0,"input ");
254         PrintRoundKey(round_key,0);
255         /* Begin with a key addition */
256         AddRoundKey(a,round_key[0]);
257         /*PrintFunction(a);*/
258         /* 9 ordinary rounds */
259         for(r = 1; r < 10; r++) {
260                 PrintFunction(a,r,"start ");
261                 SubBytes(a,S);
262                 PrintFunction(a,r,"s_box ");
263                 ShiftRows(a,0);
264                 PrintFunction(a,r,"s_row ");
265                 MixColumns(a);
266                 PrintFunction(a,r,"m_col ");
267                 AddRoundKey(a,round_key[r]);
268                 PrintRoundKey(round_key,r);
269         }
270         /* Last round is special: there is no MixColumns.  */
271         PrintFunction(a,10,"start ");
272         SubBytes(a,S);
273         PrintFunction(a,10,"s_box ");
274         ShiftRows(a,0);
275         PrintFunction(a,10,"s_row ");
276         AddRoundKey(a,round_key[10]);
277         PrintRoundKey(round_key,10);
278         PrintFunction(a,10,"output");
279 }
280 
281 
282 void PrintFunction(byte a[4][4], byte r, char b[6]) {
283         int i, j;
284         printf("R[%02d].%s    ",r,b);
285         for (j=0; j<=3; j++)
286             for (i=0; i<=3; i++)
287             printf("%02x",a[i][j]);
288             printf("\n");
289 }
290 
291 void PrintRoundKey(byte round_key[11][4][4], byte r) {
292         int i, j;
293          printf("R[%02d].k_sch     ",r);
294      for (j=0; j<=3; j++)
295      {
296          for (i=0; i<=3; i++)
297          {
298             printf("%02x",round_key[r][i][j]);
299          }
300      }
301      printf("\n");
302 }
303 
304 
305 void AddRoundKey(byte a[4][4], byte rk[4][4]) {
306         /* Xor corresponding text input and round key input bytes */
307         int i, j;
308 
309         for(i = 0; i < 4; i++)
310                 for(j=0; j<4; j++) a[i][j] ^= rk[i][j];
311 }
312 
313 
314 void SubBytes (byte a[4][4], byte box[256]) {
315         /* Replace every byte of the input by the byte at that place
316          * in the S-box.*/
317         int i, j;
318 
319         for(i = 0; i < 4; i++)
320                 for(j = 0; j < 4; j++) a[i][j] = box[a[i][j]] ;
321 }
322 
323 
324 void ShiftRows(byte a[4][4], byte d) {
325         /* Row 0 remains unchanged
326          * Row 1 rotates by 1. 
327          * Row 2 rotates by 2. 
328          * Row 3 rotates by 3. 
329          */
330         int i,j;
331         byte tmp[4];
332          for(i = 1; i < 4; i++)
333               {
334               for(j = 0; j < 4; j++)
335                  tmp[j] = a[i][(j + shifts[i][d]) % 4];
336               for(j = 0; j < 4; j++)
337                  a[i][j] = tmp[j];
338               }
339 }
340 
341 
342 byte Mul(byte c, byte d) {
343    /* Multiply two elements of GF(2^m)
344     * needed for MixColumn and InvMixColumn.
345     */
346         if (c && d) return Alogtable[(Logtable[c] + Logtable[d])%255];
347         else return 0;
348 }
349 
350 
351 void MixColumns(byte a[4][4]) {
352         /* Mix the four bytes of every column in a linear way.
353         */
354         byte b[4][4];
355         int i, j;
356         for(j = 0; j < 4; j++)
357                 for(i = 0; i < 4; i++)
358                         b[i][j] = Mul(2,a[i][j])
359                                 ^ Mul(3,a[(i + 1) % 4][j])
360                                 ^ a[(i + 2) % 4][j]
361                                 ^ a[(i + 3) % 4][j];
362         for(i = 0; i < 4; i++)
363                 for(j = 0; j < 4; j++) a[i][j] = b[i][j];
364 }
365 
366 
367 int Decrypt (byte a[4][4],
368                 byte round_key[11][4][4])
369 {
370         int r;
371 
372         /* To decrypt: apply the inverse operations of the encrypt routine,
373          *             in opposite order.
374          *
375          * (AddRoundKey is an involution: it's equal to its inverse.)
376          * (The inverse of SubBytes with table S is Subbytes with
377          *           the inverse table of S.)
378          * (The inverse of ShiftRows is ShiftRows over a suitable distance.)
379          */
380         printf("\n    Decryption\n");
381         printf("legend - round r = 10 to 0:\n");
382         printf("input:  ciphertext input\n");
383         printf("start:  state at start of round[r]\n");
384         printf("s_box:  state after s_box substitution\n");
385         printf("s_row:  state after shift row transformation\n");
386         printf("m_col:  state after inverse mix column transformation\n");
387         printf("k_sch:  key schedule value for round[r]\n");
388         printf("output: plaintext output\n\n");
389 
390         /*   First the special round:
391          *   without InvMixColumns;
392          *   with extra AddRoundKey.
393          */
394         PrintFunction(a,10,"input ");
395         PrintRoundKey(round_key,10);
396         AddRoundKey(a,round_key[10]);
397         PrintFunction(a,10,"add_k ");
398         SubBytes(a,Si);
399         PrintFunction(a,10,"s_box ");
400         ShiftRows(a,1);
401 
402         /*   9 ordinary rounds
403          */
404         for(r = 9; r > 0; r--) {
405                 PrintFunction(a,r,"start ");
406                 PrintRoundKey(round_key,r);
407                 AddRoundKey(a,round_key[r]);
408                 PrintFunction(a,r,"add_k ");
409                 InvMixColumns(a);
410                 PrintFunction(a,r,"m_col ");
411                 SubBytes(a,Si);
412                 PrintFunction(a,r,"s_box ");
413                 ShiftRows(a,1);
414         }
415 
416         /* End with the extra key addition.
417          */
418         PrintRoundKey(round_key,0);
419         AddRoundKey(a,round_key[0]);
420         PrintFunction(a,0,"output");
421 }
422 
423 void InvMixColumns(byte a[4][4]) {
424         /* Mix the four bytes of every column in a linear way.
425          * This is the opposite operation of MixColumns.
426          */
427         byte b[4][4];
428         int i, j;
429 
430         for(j = 0; j < 4; j++)
431         for(i = 0; i < 4; i++)
432                 b[i][j] = Mul(0xe,a[i][j])
433                         ^ Mul(0xb,a[(i + 1) % 4][j])
434                         ^ Mul(0xd,a[(i + 2) % 4][j])
435                         ^ Mul(0x9,a[(i + 3) % 4][j]);
436 
437         for(i = 0; i < 4; i++)
438                 for(j = 0; j < 4; j++) a[i][j] = b[i][j];
439 }
440