- aes encryption with 128 successfully tested
authorJan Hutter <jhutter@hsr.ch>
Mon, 28 Nov 2005 10:16:54 +0000 (10:16 -0000)
committerJan Hutter <jhutter@hsr.ch>
Mon, 28 Nov 2005 10:16:54 +0000 (10:16 -0000)
Source/charon/testcases/aes_cbc_crypter_test.c
Source/charon/transforms/crypters/aes_cbc_crypter.c

index 3080bc6..bbb8928 100644 (file)
@@ -75,7 +75,7 @@ void test_aes_cbc_crypter(tester_t *tester)
        logger->log_chunk(logger,RAW,"expected decrypted :", &data1);
        logger->log_chunk(logger,RAW,"decrypted :", &decrypted1);
        
-       allocator_free_chunk(&encrypted1);
+       allocator_free_chunk(&decrypted1);
         
        tester->assert_true(tester, (crypter->destroy(crypter) == SUCCESS), "destroy call test");
        
@@ -130,11 +130,77 @@ void test_aes_cbc_crypter(tester_t *tester)
        logger->log_chunk(logger,RAW,"expected decrypted :", &data2);
        logger->log_chunk(logger,RAW,"decrypted :", &decrypted2);
        
-       allocator_free_chunk(&encrypted2);
+       allocator_free_chunk(&decrypted2);
+        
+        
+       /*
+        * Test 3 of RFC3603
+        * Key       : 0x56e47a38c5598974bc46903dba290349
+        * IV        : 0x8ce82eefbea0da3c44699ed7db51b7d9
+        * Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+     *                b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+     *             c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+     *             d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+        * Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa
+     *             0f3af07a9a31a9c684db207eb0ef8e4e
+     *             35907aa632c3ffdf868bb7b29d3d46ad
+     *             83ce9f9a102ee99d49a53e87f4c3da55    
+        */
+       u_int8_t key3[] = {0x56,0xe4,0x7a,0x38,0xc5,0x59,0x89,0x74,
+                                          0xbc,0x46,0x90,0x3d,0xba,0x29,0x03,0x49};
+       chunk_t key3_chunk = {ptr: key3, len : 16};
+       u_int8_t iv3[] = {0x8c,0xe8,0x2e,0xef,0xbe,0xa0,0xda,0x3c,
+                                         0x44,0x69,0x9e,0xd7,0xdb,0x51,0xb7,0xd9};
+       chunk_t iv3_chunk = {ptr: iv3, len : 16};
+       u_int8_t ciphertext3[] = { 0xc3,0x0e,0x32,0xff,0xed,0xc0,0x77,0x4e,
+                                                          0x6a,0xff,0x6a,0xf0,0x86,0x9f,0x71,0xaa,
+                                                          0x0f,0x3a,0xf0,0x7a,0x9a,0x31,0xa9,0xc6,
+                                                          0x84,0xdb,0x20,0x7e,0xb0,0xef,0x8e,0x4e,
+                                                          0x35,0x90,0x7a,0xa6,0x32,0xc3,0xff,0xdf,
+                                                          0x86,0x8b,0xb7,0xb2,0x9d,0x3d,0x46,0xad,
+                                                          0x83,0xce,0x9f,0x9a,0x10,0x2e,0xe9,0x9d,
+                                                          0x49,0xa5,0x3e,0x87,0xf4,0xc3,0xda,0x55};
+       
+       chunk_t expected_encrypted3 = {ptr: ciphertext3, len : 64};
+       u_int8_t plaintext3[] = {0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
+                                                        0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
+                                                        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
+                                                        0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
+                                                        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
+                                                        0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
+                                                        0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
+                                                        0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf};
+       chunk_t data3 = {ptr: plaintext3, len : 64};
+       chunk_t encrypted3;
+       chunk_t decrypted3;
+                
+       crypter = (crypter_t *) aes_cbc_crypter_create(16);
+       tester->assert_true(tester, (crypter != NULL), "create call test");
+       
+       tester->assert_true(tester, (crypter->set_key(crypter,key3_chunk) == SUCCESS), "set_key call test"); 
+       
+       tester->assert_true(tester, (crypter->encrypt(crypter,data3,iv3_chunk,&encrypted3) == SUCCESS), "encrypt call test");
+       
+       tester->assert_true(tester, (memcmp(encrypted3.ptr, expected_encrypted3.ptr, 64) == 0), "Encrypted value");
+       
+       logger->log_chunk(logger,RAW,"exptected encrypted :", &expected_encrypted3);
+       logger->log_chunk(logger,RAW,"encrypted :", &encrypted3);
+       
+       tester->assert_true(tester, (crypter->decrypt(crypter,encrypted3,iv3_chunk,&decrypted3) == SUCCESS), "decrypt call test");
+       allocator_free_chunk(&encrypted3);
+
+       tester->assert_true(tester, (memcmp(decrypted3.ptr, plaintext3, 64) == 0), "decrypted value");
+       
+       logger->log_chunk(logger,RAW,"expected decrypted :", &data3);
+       logger->log_chunk(logger,RAW,"decrypted :", &decrypted3);
+       
+       allocator_free_chunk(&decrypted3);
         
        tester->assert_true(tester, (crypter->destroy(crypter) == SUCCESS), "destroy call test");
        
        
+
+       
        
        global_logger_manager->destroy_logger(global_logger_manager,logger);
 }
index 7e4b13b..1800d24 100644 (file)
@@ -84,34 +84,52 @@ struct private_aes_cbc_crypter_t {
      */
     u_int32_t    blocksize;    
     
-       
+    /**
+     * Decrypts a block.
+     * 
+     * No memory gets allocated.
+     * 
+     * @param this                     calling object
+     * @param[in] in_blk               block to decrypt
+     * @param[out] out_blk     decrypted data are written to this location
+     */
+       void (*decrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
+    /**
+     * Encrypts a block.
+     * 
+     * No memory gets allocated.
+     * 
+     * @param this                     calling object
+     * @param[in] in_blk               block to encrypt
+     * @param[out] out_blk     encrypted data are written to this location
+     */        
+       void (*encrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
 };
 
 
 /* ugly macro stuff */
-/*******************************/
 
-// CONFIGURATION OPTIONS (see also aes.h)
-//
-// 1.  Define UNROLL for full loop unrolling in encryption and decryption.
-// 2.  Define PARTIAL_UNROLL to unroll two loops in encryption and decryption.
-// 3.  Define FIXED_TABLES for compiled rather than dynamic tables.
-// 4.  Define FF_TABLES to use tables for field multiplies and inverses.
-//     Do not enable this without understanding stack space requirements.
-// 5.  Define ARRAYS to use arrays to hold the local state block. If this
-//     is not defined, individually declared 32-bit words are used.
-// 6.  Define FAST_VARIABLE if a high speed variable block implementation
-//     is needed (essentially three separate fixed block size code sequences)
-// 7.  Define either ONE_TABLE or FOUR_TABLES for a fast table driven 
-//     version using 1 table (2 kbytes of table space) or 4 tables (8
-//     kbytes of table space) for higher speed.
-// 8.  Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed 
-//     increase by using tables for the last rounds but with more table
-//     space (2 or 8 kbytes extra).
-// 9.  If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but 
-//     slower version is provided.
-// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE
-//     or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra).
+/* 1.  Define UNROLL for full loop unrolling in encryption and decryption.
+ * 2.  Define PARTIAL_UNROLL to unroll two loops in encryption and decryption.
+ * 3.  Define FIXED_TABLES for compiled rather than dynamic tables.
+ * 4.  Define FF_TABLES to use tables for field multiplies and inverses.
+ *     Do not enable this without understanding stack space requirements.
+ * 5.  Define ARRAYS to use arrays to hold the local state block. If this
+ *     is not defined, individually declared 32-bit words are used.
+ * 6.  Define FAST_VARIABLE if a high speed variable block implementation
+ *     is needed (essentially three separate fixed block size code sequences)
+ * 7.  Define either ONE_TABLE or FOUR_TABLES for a fast table driven 
+ *     version using 1 table (2 kbytes of table space) or 4 tables (8
+ *     kbytes of table space) for higher speed.
+ * 8.  Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed 
+ *     increase by using tables for the last rounds but with more table
+ *     space (2 or 8 kbytes extra).
+ * 9.  If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but 
+ *     slower version is provided.
+ * 10. If fast decryption key scheduling is needed define ONE_IM_TABLE
+ *     or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra).
+ */
 
 #define UNROLL
 //#define PARTIAL_UNROLL
@@ -150,14 +168,20 @@ struct private_aes_cbc_crypter_t {
 #error an illegal block size has been specified
 #endif  
 
-// upr(x,n): rotates bytes within words by n positions, moving bytes 
-// to higher index positions with wrap around into low positions
-// ups(x,n): moves bytes by n positions to higher index positions in 
-// words but without wrap around
-// bval(x,n): extracts a byte from a word
-
+/**
+ * Rotates bytes within words by n positions, moving bytes 
+ * to higher index positions with wrap around into low positions.
+ */ 
 #define upr(x,n)        (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n))))
+/**
+ * Moves bytes by n positions to higher index positions in 
+ * words but without wrap around.
+ */ 
 #define ups(x,n)        ((x) << 8 * (n))
+
+/**
+ * Extracts a byte from a word.
+ */
 #define bval(x,n)       ((unsigned char)((x) >> 8 * (n)))
 #define bytes2word(b0, b1, b2, b3)  \
         ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0))
@@ -941,38 +965,7 @@ static void gen_tabs(void)
     f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
 #endif
 
-// Subroutine to set the block size (if variable) in bytes, legal
-// values being 16, 24 and 32.
-
-#if defined(AES_BLOCK_SIZE)
-#define nc   (AES_BLOCK_SIZE / 4)
-#else
-#define nc   (cx->aes_Ncol)
-
-void aes_set_blk(private_aes_cbc_crypter_t *cx, int n_bytes)
-{
-#if !defined(FIXED_TABLES)
-    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
-#endif
-
-    switch(n_bytes) {
-    case 32:        /* bytes */
-    case 256:       /* bits */
-        nc = 8;
-        break;
-    case 24:        /* bytes */
-    case 192:       /* bits */
-        nc = 6;
-        break;
-    case 16:        /* bytes */
-    case 128:       /* bits */
-    default:
-        nc = 4;
-        break;
-    }
-}
-
-#endif
+#define nc   (this->aes_Ncol)
 
 // Initialise the key schedule from the user supplied key. The key
 // length is now specified in bytes - 16, 24 or 32 as appropriate.
@@ -1015,110 +1008,6 @@ switch(nc) \
 
 #endif
 
-void aes_set_key(private_aes_cbc_crypter_t *cx, const unsigned char in_key[], int n_bytes, const int f)
-{   u_int32_t    *kf, *kt, rci;
-
-#if !defined(FIXED_TABLES)
-    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
-#endif
-
-    switch(n_bytes) {
-    case 32:                    /* bytes */
-    case 256:                   /* bits */
-        cx->aes_Nkey = 8;
-        break;
-    case 24:                    /* bytes */
-    case 192:                   /* bits */
-        cx->aes_Nkey = 6;
-        break;
-    case 16:                    /* bytes */
-    case 128:                   /* bits */
-    default:
-        cx->aes_Nkey = 4;
-        break;
-    }
-
-    cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; 
-
-    cx->aes_e_key[0] = const_word_in(in_key     );
-    cx->aes_e_key[1] = const_word_in(in_key +  4);
-    cx->aes_e_key[2] = const_word_in(in_key +  8);
-    cx->aes_e_key[3] = const_word_in(in_key + 12);
-
-    kf = cx->aes_e_key; 
-    kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; 
-    rci = 0;
-
-    switch(cx->aes_Nkey)
-    {
-    case 4: do
-            {   kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++];
-                kf[5] = kf[1] ^ kf[4];
-                kf[6] = kf[2] ^ kf[5];
-                kf[7] = kf[3] ^ kf[6];
-                kf += 4;
-            }
-            while(kf < kt);
-            break;
-
-    case 6: cx->aes_e_key[4] = const_word_in(in_key + 16);
-            cx->aes_e_key[5] = const_word_in(in_key + 20);
-            do
-            {   kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++];
-                kf[ 7] = kf[1] ^ kf[ 6];
-                kf[ 8] = kf[2] ^ kf[ 7];
-                kf[ 9] = kf[3] ^ kf[ 8];
-                kf[10] = kf[4] ^ kf[ 9];
-                kf[11] = kf[5] ^ kf[10];
-                kf += 6;
-            }
-            while(kf < kt);
-            break;
-
-    case 8: cx->aes_e_key[4] = const_word_in(in_key + 16);
-            cx->aes_e_key[5] = const_word_in(in_key + 20);
-            cx->aes_e_key[6] = const_word_in(in_key + 24);
-            cx->aes_e_key[7] = const_word_in(in_key + 28);
-            do
-            {   kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++];
-                kf[ 9] = kf[1] ^ kf[ 8];
-                kf[10] = kf[2] ^ kf[ 9];
-                kf[11] = kf[3] ^ kf[10];
-                kf[12] = kf[4] ^ ls_box(kf[11],0);
-                kf[13] = kf[5] ^ kf[12];
-                kf[14] = kf[6] ^ kf[13];
-                kf[15] = kf[7] ^ kf[14];
-                kf += 8;
-            }
-            while (kf < kt);
-            break;
-    }
-
-    if(!f)
-    {   u_int32_t    i;
-        
-        kt = cx->aes_d_key + nc * cx->aes_Nrnd;
-        kf = cx->aes_e_key;
-        
-        cpy(kt, kf); kt -= 2 * nc;
-
-        for(i = 1; i < cx->aes_Nrnd; ++i)
-        { 
-#if defined(ONE_TABLE) || defined(FOUR_TABLES)
-#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES)
-            u_int32_t    f2, f4, f8, f9;
-#endif
-            mix(kt, kf);
-#else
-            cpy(kt, kf);
-#endif
-            kt -= 2 * nc;
-        }
-        
-        cpy(kt, kf);
-    }
-}
-
 // y = output word, x = input word, r = row, c = column
 // for r = 0, 1, 2 and 3 = column accessed for row r
 
@@ -1355,9 +1244,12 @@ switch(nc) \
 #endif
 #endif
 
-void aes_encrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk[], unsigned char out_blk[])
+/**
+ * Implementation of private_aes_cbc_crypter_t.encrypt_block.
+ */
+static void encrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
 {   u_int32_t        locals(b0, b1);
-    const u_int32_t  *kp = cx->aes_e_key;
+    const u_int32_t  *kp = this->aes_e_key;
 
 #if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
     u_int32_t        f2;
@@ -1367,7 +1259,7 @@ void aes_encrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 
 #if defined(UNROLL)
 
-    switch(cx->aes_Nrnd)
+    switch(this->aes_Nrnd)
     {
     case 14:    round(fwd_rnd,  b1, b0, kp         ); 
                 round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
@@ -1388,7 +1280,7 @@ void aes_encrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 #elif defined(PARTIAL_UNROLL)
     {   u_int32_t    rnd;
 
-        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
+        for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd)
         {
             round(fwd_rnd, b1, b0, kp); 
             round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc;
@@ -1400,7 +1292,7 @@ void aes_encrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 #else
     {   u_int32_t    rnd;
 
-        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
+        for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd)
         {
             round(fwd_rnd, b1, b0, kp); 
             l_copy(b0, b1); kp += nc;
@@ -1413,9 +1305,12 @@ void aes_encrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
     state_out(out_blk, b0);
 }
 
-void aes_decrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk[], unsigned char out_blk[])
+/**
+ * Implementation of private_aes_cbc_crypter_t.decrypt_block.
+ */
+static void decrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
 {   u_int32_t        locals(b0, b1);
-    const u_int32_t  *kp = cx->aes_d_key;
+    const u_int32_t  *kp = this->aes_d_key;
 
 #if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
     u_int32_t        f2, f4, f8, f9; 
@@ -1425,7 +1320,7 @@ void aes_decrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 
 #if defined(UNROLL)
 
-    switch(cx->aes_Nrnd)
+    switch(this->aes_Nrnd)
     {
     case 14:    round(inv_rnd,  b1, b0, kp         );
                 round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
@@ -1446,7 +1341,7 @@ void aes_decrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 #elif defined(PARTIAL_UNROLL)
     {   u_int32_t    rnd;
 
-        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
+        for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd)
         {
             round(inv_rnd, b1, b0, kp); 
             round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc;
@@ -1458,7 +1353,7 @@ void aes_decrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
 #else
     {   u_int32_t    rnd;
 
-        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
+        for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd)
         {
             round(inv_rnd, b1, b0, kp); 
             l_copy(b0, b1); kp += nc;
@@ -1471,11 +1366,6 @@ void aes_decrypt(const private_aes_cbc_crypter_t *cx, const unsigned char in_blk
     state_out(out_blk, b0);
 }
 
-
-
-/* *************************/
-
-
 /**
  * Implementation of crypter_t.decrypt.
  */
@@ -1506,7 +1396,7 @@ static status_t decrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t
        in+=pos;
        out+=pos;
        while(pos>=0) {
-               aes_decrypt(this,in,out);
+               this->decrypt_block(this,in,out);
                if (pos==0)
                        iv_i=(const u_int32_t*) (iv.ptr);
                else
@@ -1561,7 +1451,7 @@ static status_t encrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t
                *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4]));
                *((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8]));
                *((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12]));
-               aes_encrypt(this,out,out);
+               this->encrypt_block(this,out,out);
                in+=16;
                out+=16;
                pos+=16;
@@ -1582,7 +1472,94 @@ static size_t get_block_size (private_aes_cbc_crypter_t *this)
  */
 static status_t set_key (private_aes_cbc_crypter_t *this, chunk_t key)
 {
-       aes_set_key(this, key.ptr, key.len,0);
+       u_int32_t    *kf, *kt, rci, f = 0;
+       u_int8_t *in_key = key.ptr;
+
+       if (key.len != this->blocksize)
+       {
+               return INVALID_ARG;
+       }
+
+    this->aes_Nrnd = (this->aes_Nkey > (this->aes_Ncol) ? this->aes_Nkey : (this->aes_Ncol)) + 6; 
+
+    this->aes_e_key[0] = const_word_in(in_key     );
+    this->aes_e_key[1] = const_word_in(in_key +  4);
+    this->aes_e_key[2] = const_word_in(in_key +  8);
+    this->aes_e_key[3] = const_word_in(in_key + 12);
+
+    kf = this->aes_e_key; 
+    kt = kf + nc * (this->aes_Nrnd + 1) - this->aes_Nkey; 
+    rci = 0;
+
+    switch(this->aes_Nkey)
+    {
+    case 4: do
+            {   kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++];
+                kf[5] = kf[1] ^ kf[4];
+                kf[6] = kf[2] ^ kf[5];
+                kf[7] = kf[3] ^ kf[6];
+                kf += 4;
+            }
+            while(kf < kt);
+            break;
+
+    case 6: this->aes_e_key[4] = const_word_in(in_key + 16);
+            this->aes_e_key[5] = const_word_in(in_key + 20);
+            do
+            {   kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++];
+                kf[ 7] = kf[1] ^ kf[ 6];
+                kf[ 8] = kf[2] ^ kf[ 7];
+                kf[ 9] = kf[3] ^ kf[ 8];
+                kf[10] = kf[4] ^ kf[ 9];
+                kf[11] = kf[5] ^ kf[10];
+                kf += 6;
+            }
+            while(kf < kt);
+            break;
+
+    case 8: this->aes_e_key[4] = const_word_in(in_key + 16);
+            this->aes_e_key[5] = const_word_in(in_key + 20);
+            this->aes_e_key[6] = const_word_in(in_key + 24);
+            this->aes_e_key[7] = const_word_in(in_key + 28);
+            do
+            {   kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++];
+                kf[ 9] = kf[1] ^ kf[ 8];
+                kf[10] = kf[2] ^ kf[ 9];
+                kf[11] = kf[3] ^ kf[10];
+                kf[12] = kf[4] ^ ls_box(kf[11],0);
+                kf[13] = kf[5] ^ kf[12];
+                kf[14] = kf[6] ^ kf[13];
+                kf[15] = kf[7] ^ kf[14];
+                kf += 8;
+            }
+            while (kf < kt);
+            break;
+    }
+
+    if(!f)
+    {   u_int32_t    i;
+        
+        kt = this->aes_d_key + nc * this->aes_Nrnd;
+        kf = this->aes_e_key;
+        
+        cpy(kt, kf); kt -= 2 * nc;
+
+        for(i = 1; i < this->aes_Nrnd; ++i)
+        { 
+#if defined(ONE_TABLE) || defined(FOUR_TABLES)
+#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES)
+            u_int32_t    f2, f4, f8, f9;
+#endif
+            mix(kt, kf);
+#else
+            cpy(kt, kf);
+#endif
+            kt -= 2 * nc;
+        }
+        
+        cpy(kt, kf);
+    }
+
        return SUCCESS;
 }
 
@@ -1595,7 +1572,9 @@ static status_t destroy (private_aes_cbc_crypter_t *this)
        return SUCCESS;
 }
 
-
+/*
+ * Described in header
+ */
 aes_cbc_crypter_t *aes_cbc_crypter_create(size_t blocksize)
 {
        private_aes_cbc_crypter_t *this = allocator_alloc_thing(private_aes_cbc_crypter_t);
@@ -1610,19 +1589,21 @@ aes_cbc_crypter_t *aes_cbc_crypter_create(size_t blocksize)
     switch(blocksize) {
     case 32:        /* bytes */
         this->aes_Ncol = 8;
+        this->aes_Nkey = 8;
         this->blocksize = blocksize;
         break;
     case 24:        /* bytes */
         this->aes_Ncol = 6;
+        this->aes_Nkey = 6;
         this->blocksize = blocksize;
         break;
     case 16:        /* bytes */
     default:
         this->aes_Ncol = 4;
+        this->aes_Nkey = 4;
         this->blocksize = 16;
         break;
     }
-       
 
        /* functions of crypter_t interface */  
        this->public.crypter_interface.encrypt = (status_t (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
@@ -1634,6 +1615,9 @@ aes_cbc_crypter_t *aes_cbc_crypter_create(size_t blocksize)
        /* public functions */
        this->public.destroy = (status_t (*) (aes_cbc_crypter_t *)) destroy;
        
+       /* private functions */
+       this->decrypt_block = decrypt_block;
+       this->encrypt_block = encrypt_block;
        
        return &(this->public);
 }