Skip to content
Snippets Groups Projects
rijndael.c 17.8 KiB
Newer Older
Rafael Sevilla's avatar
Rafael Sevilla committed
/* rijndael - An implementation of the Rijndael cipher.
Rafael Sevilla's avatar
Rafael Sevilla committed
 * Copyright (C) 2000 Rafael R. Sevilla <dido@pacific.net.ph>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "rijndael.h"

#include <assert.h>
#include <stdio.h>
Rafael Sevilla's avatar
Rafael Sevilla committed
#include <stdlib.h>
#include <string.h>

/* These tables combine both the S-boxes and the mixcolumn transformation, so
   that we can perform a round's encryption or by means of four table lookups
   and four XOR's per column of state.  They were generated by the
   makertbls.pl script. */
static const UINT32 dtbl[] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 
  0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 
  0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 
  0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 
  0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 
  0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 
  0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 
  0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 
  0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 
  0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 
  0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 
  0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 
  0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 
  0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, 
  0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 
  0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 
  0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 
  0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 
  0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 
  0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, 
  0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 
  0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 
  0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 
  0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, 
  0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 
  0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 
  0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, 
  0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 
  0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 
  0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, 
  0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 
  0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 
  0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 
  0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 
  0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 
  0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 
  0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 
  0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, 
  0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 
  0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 
  0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 
  0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, 
  0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 
  0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 
  0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 
  0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 
  0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 
  0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 
  0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 
  0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 
  0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 
  0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 
  0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 
  0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, 
  0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 
  0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 
  0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 
  0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 
  0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 
  0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, 
  0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 
  0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 
  0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 
  0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, 
};

static const UINT32 itbl[] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 
  0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, 
  0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 
  0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 
  0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 
  0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 
  0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 
  0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 
  0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 
  0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 
  0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 
  0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 
  0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 
  0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 
  0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, 
  0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 
  0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 
  0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 
  0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 
  0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd, 
  0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 
  0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060, 
  0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 
  0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, 
  0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 
  0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 
  0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 
  0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 
  0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b, 
  0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 
  0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 
  0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 
  0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 
  0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 
  0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 
  0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 
  0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 
  0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, 
  0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 
  0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 
  0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 
  0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 
  0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 
  0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 
  0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 
  0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 
  0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83, 
  0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, 
  0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 
  0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 
  0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 
  0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 
  0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 
  0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 
  0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 
  0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 
  0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 
  0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 
  0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 
  0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, 
  0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 
  0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 
  0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 
  0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, 
};


/* Needed only for the key schedule and for final rounds */
static const UINT8 sbox[256] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171,
  118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164,
  114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113,
  216,  49,  21,  4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226,
  235,  39, 178, 117,  9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214,
  179,  41, 227,  47, 132, 83, 209,   0, 237,  32, 252, 177,  91, 106, 203,
  190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69,
  249,   2, 127,  80,  60, 159, 168, 81, 163,  64, 143, 146, 157,  56, 245,
  188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,
  23, 196, 167, 126,  61, 100,  93,  25, 115, 96, 129,  79, 220,  34,  42,
  144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
  6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 
  141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
  181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
  248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223, 
  140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,
  22, 
};

static const UINT8 isbox[256] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215,
  251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222,
  233, 203, 84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66,
  250, 195,  78,  8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73,
  109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92,
  204,  93, 101, 182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,
  70,  87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10, 247,
  228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,  63,  15,   2,
  193, 175, 189,   3,   1,  19, 138, 107,  58, 145,  17,  65,  79, 103, 220,
  234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116,  34, 231, 173,
  53, 133, 226, 249,  55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,
  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75,
  198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81,
  127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 160,
  224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97,
  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12,
  125, 
};

/* Used only by the key schedule */
static const UINT8 Logtable[256] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238, 223,  3,
  100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200, 248, 105,  28,
  193, 125, 194,  29, 181, 249, 185,  39, 106,  77, 228, 166, 114, 154, 201,
  9, 120, 101,  47, 138,   5,  33,  15, 225,  36,  18, 240, 130,  69,  53,
  147, 218, 142, 150, 143, 219, 189,  54, 208, 206, 148,  19,  92, 210, 241,
  64,  70, 131,  56, 102, 221, 253,  48, 191,   6, 139,  98, 179,  37, 226,
  152,  34, 136, 145,  16, 126, 110,  72, 195, 163, 182,  30,  66,  58, 107,
  40,  84, 250, 133,  61, 186, 43, 121,  10,  21, 155, 159,  94, 202,  78,
  212, 172, 229, 243, 115, 167,  87, 175,  88, 168,  80, 244, 234, 214, 116,
  79, 174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235,  22,  11,
  245,  89, 203,  95, 176, 156, 169,  81, 160, 127,  12, 246, 111,  23, 196,
  73, 236, 216,  67,  31,  45, 164, 118, 123, 183, 204, 187,  62,  90, 251,
  96, 177, 134,  59,  82, 161, 108, 170,  85,  41, 157, 151, 178, 135, 144,
  97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209, 83,  57, 132,
  60,  65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171, 68,  17,
  146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153, 227, 165, 103,  
  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128, 192, 247, 112,   7, 
};

static const UINT8 Alogtable[256] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,  19, 
  53, 95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,  30,  34,
  102, 170, 229,  52,  92, 228,  55,  89, 235,  38, 106, 190, 217, 112, 144,
  171, 230,  49,  83, 245,   4,  12,  20,  60,  68, 204,  79, 209, 104, 184,
  211, 110, 178, 205,  76, 212, 103, 169, 224,  59,  77, 215,  98, 166, 241,
  8,  24,  40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129, 152,
  179, 206,  73, 219, 118, 154, 181, 196,  87, 249,  16,  48,  80, 240,  11,
  29,  39, 105, 187, 214,  97, 163, 254,  25,  43, 125, 135, 146, 173, 236,
  47, 113, 147, 174, 233,  32,  96, 160, 251,  22,  58,  78, 210, 109, 183,
  194,  93, 231,  50,  86, 250,  21,  63,  65, 195,  94, 226,  61,  71, 201,
  64, 192,  91, 237,  44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172,
  239,  42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193,  88,
  232,  35, 101, 175, 234,  37, 111, 177, 200,  67, 197,  84, 252,  31,  33,
  99, 165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,  69, 207,
  74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,  18,
  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,  13,  23,
  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180, 199,  82, 246, 1, 
};

#define ROTBYTE(x) (((x) >> 8) | (((x) & 0xff) << 24))
#define ROTRBYTE(x) (((x) << 8) | (((x) >> 24) & 0xff))
#define SUBBYTE(x, box) (((box)[((x) & 0xff)]) | \
                        ((box)[(((x) >> 8) & 0xff)] << 8) | \
                        ((box)[(((x) >> 16) & 0xff)] << 16) | \
                        ((box)[(((x) >> 24) & 0xff)] << 24))

static UINT8
xtime(UINT8 a)
{
  UINT8 b;

  b = (a & 0x80) ? 0x1b : 0;
  a<<=1;
  a^=b;
  return(a);
}

static UINT8
mul(UINT8 a, UINT8 b)
{
  if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255];
  else return 0;
}

static void
inv_mix_column(UINT32 *a, UINT32 *b)
{
  UINT8 c[4][4];
  int i, j;
	
  for(j = 0; j < 4; j++) {
    for(i = 0; i < 4; i++) {
      c[j][i] = mul(0xe, (a[j] >> i*8) & 0xff)
	^ mul(0xb, (a[j] >> ((i+1)%4)*8) & 0xff)
	^ mul(0xd, (a[j] >> ((i+2)%4)*8) & 0xff)
	^ mul(0x9, (a[j] >> ((i+3)%4)*8) & 0xff);
    }
  }
  for(i = 0; i < 4; i++) {
    b[i] = 0;
    for(j = 0; j < 4; j++)
      b[i] |= c[i][j] << (j*8);
  }
}

void
rijndael_setup(RIJNDAEL_context *ctx, size_t keysize, const UINT8 *key)
{
  int nk, nr, i, lastkey;
  UINT32 temp, rcon;

  /* Truncate keysizes to the valid key sizes provided by Rijndael */
  if (keysize >= 32) {
    nk = 8;
    nr = 14;
  } else if (keysize >= 24) {
    nk = 6;
    nr = 12;
  } else {			/* must be 16 or more */
Rafael Sevilla's avatar
Rafael Sevilla committed
    nk = 4;
    nr = 10;
  }

  lastkey = (RIJNDAEL_BLOCKSIZE/4) * (nr + 1);
  ctx->nrounds = nr;
  rcon = 1;
  for (i=0; i<nk; i++) {
    ctx->keys[i] = key[i*4] + (key[i*4+1]<<8) + (key[i*4+2]<<16) +
      (key[i*4+3]<<24);
  }

  for (i=nk; i<lastkey; i++) {
    temp = ctx->keys[i-1];
    if (i % nk == 0) {
      temp = SUBBYTE(ROTBYTE(temp), sbox) ^ rcon;
      rcon = (UINT32)xtime((UINT8)rcon&0xff);
    } else if (nk > 6 && (i%nk) == 4) {
      temp = SUBBYTE(temp, sbox);
    }
    ctx->keys[i] = ctx->keys[i-nk] ^ temp;
  }
  /* Generate the inverse keys */
  for (i=0; i<4; i++) {
    ctx->ikeys[i] = ctx->keys[i];
    ctx->ikeys[lastkey-4 + i] = ctx->keys[lastkey-4 + i];
  }
  for (i=4; i<lastkey-4; i+=4)
    inv_mix_column(&(ctx->keys[i]), &(ctx->ikeys[i]));
}

/* Key addition that also packs every byte in the key to a word rep. */
static void
key_addition_8to32(const UINT8 *txt, UINT32 *keys, UINT32 *out)
{
  const UINT8 *ptr;
  int i, j;
  UINT32 val;

  ptr = txt;
  for (i=0; i<4; i++) {
    val = 0;
    for (j=0; j<4; j++)
      val |= (*ptr++ << 8*j);
    out[i] = keys[i]^val;
  }
}

static void
key_addition32(const UINT32 *txt, UINT32 *keys, UINT32 *out)
{
  int i;

  for (i=0; i<4; i++)
    out[i] = keys[i] ^ txt[i];
}

static void
key_addition32to8(const UINT32 *txt, UINT32 *keys, UINT8 *out)
{
  UINT8 *ptr;
  int i, j;
  UINT32 val;

  ptr = out;
  for (i=0; i<4; i++) {
    val = txt[i] ^ keys[i];
    for (j=0; j<4; j++)
      *ptr++ = (val >> 8*j) & 0xff;
  }
}

static const int idx[4][4] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  { 0, 1, 2, 3 },
  { 1, 2, 3, 0 },
  { 2, 3, 0, 1 },
  { 3, 0, 1, 2 } };

void
rijndael_encrypt(RIJNDAEL_context *ctx,
		 const UINT8 *plaintext,
		 UINT8 *ciphertext)
{
  int r, j;
  UINT32 wtxt[4], t[4];		/* working ciphertext */
  UINT32 e;

  key_addition_8to32(plaintext, &(ctx->keys[0]), wtxt);
  for (r=1; r<ctx->nrounds; r++) {
    for (j=0; j<4; j++) {
      t[j] = dtbl[wtxt[j] & 0xff] ^
	ROTRBYTE(dtbl[(wtxt[idx[1][j]] >> 8) & 0xff]^
		 ROTRBYTE(dtbl[(wtxt[idx[2][j]] >> 16) & 0xff] ^
			  ROTRBYTE(dtbl[(wtxt[idx[3][j]] >> 24) & 0xff])));
    }
    key_addition32(t, &(ctx->keys[r*4]), wtxt);
  }
  /* last round is special: there is no mixcolumn, so we can't use the big
     tables. */
  for (j=0; j<4; j++) {
    e = wtxt[j] & 0xff;
    e |= (wtxt[idx[1][j]]) & (0xff << 8);
    e |= (wtxt[idx[2][j]]) & (0xff << 16);
    e |= (wtxt[idx[3][j]]) & (0xff << 24);
    t[j] = e;
  }
  for (j=0; j<4; j++)
    t[j] = SUBBYTE(t[j], sbox);
  key_addition32to8(t, &(ctx->keys[4*ctx->nrounds]), ciphertext);
}

static const int iidx[4][4] = {
Rafael Sevilla's avatar
Rafael Sevilla committed
  { 0, 1, 2, 3 },
  { 3, 0, 1, 2 },
  { 2, 3, 0, 1 },
  { 1, 2, 3, 0 } };

void
rijndael_decrypt(RIJNDAEL_context *ctx,
		 const UINT8 *ciphertext,
		 UINT8 *plaintext)
{
  int r, j;
  UINT32 wtxt[4], t[4];		/* working ciphertext */
  UINT32 e;

  key_addition_8to32(ciphertext, &(ctx->ikeys[4*ctx->nrounds]), wtxt);
  for (r=ctx->nrounds-1; r> 0;  r--) {
    for (j=0; j<4; j++) {
      t[j] = itbl[wtxt[j] & 0xff] ^
	ROTRBYTE(itbl[(wtxt[iidx[1][j]] >> 8) & 0xff]^
		 ROTRBYTE(itbl[(wtxt[iidx[2][j]] >> 16) & 0xff] ^
			  ROTRBYTE(itbl[(wtxt[iidx[3][j]] >> 24) & 0xff])));
    }
    key_addition32(t, &(ctx->ikeys[r*4]), wtxt);
  }
  /* last round is special: there is no mixcolumn, so we can't use the big
     tables. */
  for (j=0; j<4; j++) {
    e = wtxt[j] & 0xff;
    e |= (wtxt[iidx[1][j]]) & (0xff << 8);
    e |= (wtxt[iidx[2][j]]) & (0xff << 16);
    e |= (wtxt[iidx[3][j]]) & (0xff << 24);
    t[j] = e;
  }
  for (j=0; j<4; j++)
    t[j] = SUBBYTE(t[j], isbox);
  key_addition32to8(t, &(ctx->ikeys[0]), plaintext);
}