Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does libgcrypt increment the counter for CTR mode?

I have a file encrypted with AES-256 using libgcrypt's CTR mode implementation. I want to be able to decrypt the file in parts (e.g. decrypting blocks 5-10 out of 20 blocks without decrypting the whole file).

I know that by using CTR mode, I should be able to do it. All I need is to know the correct counter. The problem lies in the fact that all I have is the initial counter for block 0. If I want to decrypt block 5 for example, I need another counter, one that is achieved by doing some action on the initial counter for each block from 0 to 5.

I can't seem to find an API that libgcrypt exposes in order to calculate counter for later blocks given the initial counter.

How can I calculate the counter of later blocks (e.g. block #5) given the counter of block #0?

like image 424
E1adi Avatar asked Dec 27 '18 14:12

E1adi


People also ask

What are the advantages of CTR mode?

Advantages and disadvantages of using the CTR mode Since blocks are independent of one another with the CTR mode, once the pad vectors have been generated, both encryption and decryption of blocks can be parallelly done. The lack of interdependency also means that the CTR mode is tolerant to a loss in blocks.

Is CTR mode malleable?

Security strength CTR mode works faster than XTS-AES mode but CTR mode is malleable – an attacker can flip plaintext bits by simply flipping the corresponding ciphertext bits.


1 Answers

When in doubt, go to the source. Here's the code in gcrypt's generic CTR mode implementation (_gcry_cipher_ctr_encrypt() in cipher-ctr.c) that increments the counter:

for (i = blocksize; i > 0; i--)
  {
    c->u_ctr.ctr[i-1]++;
    if (c->u_ctr.ctr[i-1] != 0)
      break;
  }

There are other, more optimized implementations of counter incrementing found in other places in the libgcrypt source, e.g. in the various cipher-specific fast bulk CTR encryption implementations, but this generic one happens to be nice and readable. (Of course, all those alternative implementations need to produce the same sequence of counter values anyway, so that gcrypt stays compatible with itself.)

OK, so what does it actually do?

Well, looking at the context (or, more specifically, cipher-internal.h), it's clear that c->u_ctr.ctr is an array of blocksize unsigned bytes (where blocksize equals 16 bytes for AES). The code above increments its last byte by one, and checks if the result wrapped around to zero. If it didn't, it stops; if it did wrap, the code then moves to the second-to-last byte, increments it, checks to see if it wrapped, and keeps looping until it either finds a byte that doesn't wrap around when incremented, or it has incremented all of the blocksize bytes.

So, for example, if your original counter value was {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, then after incrementing it would become {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}. If incremented again, it would become {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, then {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3}, and so on up to {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255}, after which the next counter value would be {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} (and after that {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3}, etc.).

Of course, what this is really doing is just arithmetically incrementing a single (blocksize × 8)-bit integer, stored in memory in big-endian byte order.

like image 178
Ilmari Karonen Avatar answered Sep 20 '22 07:09

Ilmari Karonen