aboutsummaryrefslogtreecommitdiffstats
path: root/Source/charon/transforms
diff options
context:
space:
mode:
Diffstat (limited to 'Source/charon/transforms')
-rw-r--r--Source/charon/transforms/crypters/aes_cbc_crypter.c354
1 files changed, 169 insertions, 185 deletions
diff --git a/Source/charon/transforms/crypters/aes_cbc_crypter.c b/Source/charon/transforms/crypters/aes_cbc_crypter.c
index 7e4b13bde..1800d2409 100644
--- a/Source/charon/transforms/crypters/aes_cbc_crypter.c
+++ b/Source/charon/transforms/crypters/aes_cbc_crypter.c
@@ -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);
}