5

In the PHP documentation for mcrypt_get_iv_size it is stated that the return value will be zero when the algorithm / block mode combination does not use an IV:

Returns the size of the Initialization Vector (IV) in bytes. On error the function returns FALSE. If the IV is ignored in the specified cipher/mode combination zero is returned.

When I call this function with MCRYPT_DES as the algo and MCRYPT_MODE_ECB as the mode it returns 8 (eight) instead of the expected 0 (zero).

It's my understanding that ECB does not and can not use an IV, and hence I expect the zero value. Is this incorrect, is the documentation incorrect, or am I missing something else?

The following snippet demonstrates the problem:

<?php
// I expect this call to return zero.
$size = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB);
echo 'IV Size: ' . $size . PHP_EOL;

Please note that I'm not actually using ECB for real-world encryption, I'm simply trying to find a reliable way for determining if an arbitrary algo/mode requires an IV. (I notice that the mcrypt library has a function "mcrypt_enc_mode_has_iv", but there does not seem to be an equivalent PHP function).

I'm using PHP v5.3.12 with libmcrypt 2.5.8_1.

Update with possible workaround:

Looking at the libmcrypt source it seems as though mcrypt_enc_get_iv_size() will always return the block size for any block cipher mode, but falls back to "asking" the algorithm for stream modes.

int mcrypt_enc_get_iv_size(MCRYPT td)
{
    if (mcrypt_enc_is_block_algorithm_mode(td) == 1) {
        return mcrypt_enc_get_block_size(td);
    } else {
        return mcrypt_get_algo_iv_size(td);
    }
}

The mcrypt_get_algo_iv_size() call is forwarded on to the algorithm library's _mcrypt_get_algo_iv_size() function. So hopefully this means if I handle the ECB case manually it should yield the correct result for those algorithms that require an IV in stream mode.

jmalloc
  • 181
  • 1
  • 5

1 Answers1

1

You are right, ECB does not use an IV, as it is also pointed out in the PHP documentation for mcrypt_get_iv_size:

One of the MCRYPT_MODE_modename constants, or one of the following strings: "ecb", "cbc", "cfb", "ofb", "nofb" or "stream". The IV is ignored in ECB mode as this mode does not require it. You will need to have the same IV (think: starting point) both at encryption and decryption stages, otherwise your encryption will fail.

Why mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB) returns 8 is odd. Intentional or not, you should disregard it.

kba
  • 19,333
  • 5
  • 62
  • 89
  • 1
    I can't simply disregard it unfortunately as ECB alone is not a reliable indicator of whether or not an IV is required (elsewhere in the documentation it states that some ciphers require an IV when using stream mode). I think I will lodge a PHP bug report and see if they lean towards changing the code or the documentation :). Thank you for your reply. – jmalloc Jul 25 '12 at 02:41
  • 1
    ECB as block mode is a reliable indicator. That you use ECB to implement another mode does not change this fact. – Maarten Bodewes Jul 25 '12 at 07:49
  • 1
    Note that I'm all for changing the result of the method and/or the documentation, although I would opt for returning -1 to create a fail fast situation. – Maarten Bodewes Jul 25 '12 at 07:57
  • 1
    @jmalloc ECB **never** uses an IV, so it is very much a reliable indicator. – kba Jul 25 '12 at 14:27
  • @kba That's true, but it's not the **only** case where an IV is not used. Some algorithms use an IV in STREAM mode, and others do not (according to docs, no direct experience here). I'm now checking ECB manually as per my update to the question. – jmalloc Jul 26 '12 at 01:42