1

I have the following code working for AES-256 ECB encryption using a simple byte-oriented AES-256 library I found here.

Main:

#define DUMP(s, i, buf, sz)  {printf(s); \
for (i = 0; i < (sz);i++) \
printf("%02x ", buf[i]); \
printf("\n");}

int main (int argc, char *argv[])
{
aes256_context ctx; 
uint8_t key[32] = "39P8TXDMBCYF4C1NI1CDFJ1WL6P5TTKZ";
uint8_t buf[16] = "KUC7EWG6M2D1WW8F";
uint8_t i;

DUMP("txt: ", i, buf, sizeof(buf));
DUMP("key: ", i, key, sizeof(key));
printf("---\n");

aes256_init(&ctx, key);
aes256_encrypt_ecb(&ctx, buf);

DUMP("enc: ", i, buf, sizeof(buf));

aes256_init(&ctx, key);
aes256_decrypt_ecb(&ctx, buf);
DUMP("dec: ", i, buf, sizeof(buf));

aes256_done(&ctx);
return 0;
}

Encryption function:

void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
for(i = 1, rcon = 1; i < 14; ++i)
{
aes_subBytes(buf);
aes_shiftRows(buf);
aes_mixColumns(buf);
if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
}
aes_subBytes(buf);
aes_shiftRows(buf);
aes_expandEncKey(ctx->key, &rcon);
aes_addRoundKey(buf, ctx->key);
} /* aes256_encrypt */

I want to add an IV to this program to create AES-256 CBC mode. From what I understand, IV implementation is as follows:

  1. XOR the first block with the IV.
  2. XOR all following blocks with the cipher text of the previous block.

My question is what does the logic look like? How do I implement that into my code?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Joe Sw
  • 25
  • 5

1 Answers1

0

The logic and explanations can be found in a few places. For example in: ECB vs CBC or Block cipher mode of operation.

CBC = Cipher Block Chaining is a way of connecting blocks together.

What is does is instead of just processing each block separately, every block will be XOR’ed with the encrypted previous block. This effectively means that every block depends on the output of the previous block.

Each block is XORed with the ciphertext of the previous block as it is explained by diagrams in the quoted articles.

In practice once one block is encrypted by ECB encription:

 Cipher((state_t*)buf, ctx->RoundKey);

as in

void AES_ECB_encrypt(struct AES_ctx *ctx,const uint8_t* buf)
{
  // The next function call encrypts the PlainText with the Key using AES algorithm.
  Cipher((state_t*)buf, ctx->RoundKey);
}

CBC is achieved by XOR with IV on the block, ECB on the same block and moving along the blocks in the buffer.

Example of XOR with IV:

static void XorWithIv(uint8_t* buf, uint8_t* Iv)
{
  uint8_t i;
  for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
  {
    buf[i] ^= Iv[i];
  }
}

Example of CBC with the use of XOR with IV and ECB :

void AES_CBC_encrypt_buffer(struct AES_ctx *ctx,uint8_t* buf, uint32_t length)
{
  uintptr_t i;
  uint8_t *Iv = ctx->Iv;
  for (i = 0; i < length; i += AES_BLOCKLEN)
  {
    XorWithIv(buf, Iv);
    Cipher((state_t*)buf, ctx->RoundKey);
    Iv = buf;
    buf += AES_BLOCKLEN;
    //printf("Step %d - %d", i/16, i);
  }
  /* store Iv in ctx for next call */
  memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}

The above implementation comes from tiny-AES and you may want to study it and adapt it to your needs. I hope it helps.

sg7
  • 6,108
  • 2
  • 32
  • 40