Because Chr() is vulnerable to "cache-timing" attack and pack() is not?

Asked

Viewed 115 times

5

Out of curiosity I am looking for and slow many things about cryptography and also looking for some libraries in pure PHP, such as Sodium_compat, for the sole reason that I understand much more of PHP compared to C, which is ideal for encryption, as far as I know.

However something caught my eye on following part:

/**
* Use pack() and binary operators to turn the two integers
* into hexadecimal characters. We don't use chr() here, because
* it uses a lookup table internally and we want to avoid
* cache-timing side-channels.
*/
$hex .= pack(
'CC',
(55 + $b + ((($b - 10) >> 8) & ~6)),
(55 + $c + ((($c - 10) >> 8) & ~6))
);

I just couldn’t find much information about the cache-timing, remembering that there is the cache-timing attack and the timing attack, which are separate things (or not?), the second has more information.

I found this information here, which is the most summarized and there is this other reply and comment that seems to be almost the answer to this question, but I’m not sure. Even based on the comment of the code I assume the problem is that the chr() uses some kind of "array" (that would be the lookup table internally?) as long as the pack() but as then the pack() is able to convert the whole to hexadecimal?

The point is, the pack() supposedly is not vulnerable while the chr() has such a problem, this is not even mentioned in the PHP documentation, perhaps because it is something very specific. What’s different about the functions inside? How do they convert the integers and why can one convert "more securely than the other"? Why both are not vulnerable?

  • I don’t know much about cryptography (it’s something that’s been on my list to study for a while), but I believe so, the LUT internally is basically an array, similar to the ASCII table itself. By the comments, the function avoid using ULT precisely to make the function slower, ie, take longer to compute it. I believe this is quite useful against attacks Brute-force Attack.

2 answers

3


The implementation of the function pack() is much more robust compared to function chr().

It has several sanitizations and validations, among them, the RFC 4648 Encoding

An excerpt from the pack() function routines where input values are filtered:

static void php_pack(zval *val, size_t size, int *map, char *output)
{
    size_t i;
    char *v;

    convert_to_long_ex(val);
    v = (char *) &Z_LVAL_P(val);

    for (i = 0; i < size; i++) {
        *output++ = v[map[i]];
    }
}

PHP-src: https://github.com/php/php-src/blob/master/ext/standard/pack.c

The functions as ord() and chr(), not much to comment on. Just see how simple implementation does not have filters like in the function pack():

PHP_FUNCTION(ord)
{
    char   *str;
    size_t str_len;

    ZEND_PARSE_PARAMETERS_START(1, 1)
        Z_PARAM_STRING(str, str_len)
    ZEND_PARSE_PARAMETERS_END();

    RETURN_LONG((unsigned char) str[0]);
}
/* }}} */


PHP_FUNCTION(chr)
{
    zend_long c;

    if (ZEND_NUM_ARGS() != 1) {
        WRONG_PARAM_COUNT;
    }

    ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
        Z_PARAM_LONG(c)
    ZEND_PARSE_PARAMETERS_END_EX(c = 0);

    c &= 0xff;
    if (CG(one_char_string)[c]) {
        ZVAL_INTERNED_STR(return_value, CG(one_char_string)[c]);
    } else {
        ZVAL_NEW_STR(return_value, zend_string_alloc(1, 0));
        Z_STRVAL_P(return_value)[0] = (char)c;
        Z_STRVAL_P(return_value)[1] = '\0';
    }
}

PHP-src: https://github.com/php/php-src/blob/master/ext/standard/string.c

This is simple in this way for performance reasons because you don’t always need to filter. Filters are best suited for employing encryption routines, security, etc.

Table look-ups

Even based on the comment of the code I assume the problem is Chr() uses some sort of "array" (that would be the lookup table internally?)

Yes, this is how most programming languages use in their string manipulation functions.

The "table look-ups" method has known exploits and is heavily exploited by attacks. A solution proposal is to use logical "Constant-time" sequence operations (RFC 4648) or at least by references other than the secret key data (secret data). This issue, at the moment, is under open discussion, without a concrete definition.

2

When it comes to cryptography there are several aspects that should be taken into account.

The fact of wearing pack() instead of char() refers to a concept called Binary safe making both input and output consistent in terms of string manipulation for example.

And as stated earlier in one of the answers you researched, depending on how the encryption is done and the algorithm there is the possibility to identify the mode and maybe functions used to encrypt through the behavior and exploit a certain existing vulnerability.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.