cencryptionkeyaespolarssl

Cipher key is always 20-bytes (with null padding) in crypt_and_hash in PolarSSL


I'm writing an application whose security is based on the crypt_and_hash example provided with the PolarSSL package. In the example, crypt_and_hash takes in a key (supplied via a command-line argument) and a random 16-byte IV. It then garbles them together 8192 times (for reasons that I don't know, but that's besides the question):

    memset( digest, 0,  32 );
    memcpy( digest, IV, 16 );

    for( i = 0; i < 8192; i++ )
    {
        md_starts( &md_ctx );
        md_update( &md_ctx, digest, 32 );
        md_update( &md_ctx, key, keylen );
        md_finish( &md_ctx, digest );

    }

Then, it takes the output and uses is to set the key in the cipher context via cipher_setkey, which is later used to perform all the encryption/decryption operations:

    if( cipher_setkey( &cipher_ctx, digest, cipher_info->key_length,
                       POLARSSL_ENCRYPT ) != 0 )

I noticed that when crypt_and_hash creates its digest, it sets only 20 bytes in its buffer, followed by 12 null bytes, regardless of the encryption scheme and the size of the key supplied. I tried different schemes and key sizes to test that. Shouldn't the key size be according to the encryption (e.g. 32 bytes for AES-256 and 16 bytes for AES-128)? Why is it always 20?


Solution

  • What you have here is a proprietary Password Based Key Derivation Function (PBKDF). This function seems to allow for key strengthening or key stretching, but not for key expansion.

    Key strengthening can be used to make it harder to brute force a key value (or password value) if this key is not fully random. It is implemented by the loop using the IV (which is actually a salt) and key within a cryptographic hash function. If you receive 20 bytes, this is likely to be SHA-1 as it has 160 bits of output.

    Key expansion is not provided by the algorithm. Key expansion is what you are looking at: distribute the calculated random number over an X number of bits. It is relatively easily implemented; probably the best thing to do is to have a look at the key expansion algorithm of HKDF.

    Currently the scheme is however limited by the output of the hash within the PBKDF. Of course, if you were to use SHA-256 you would have enough entropy for one AES-256 key. Or, if you use a different salt for each encryption, you could use SH-384 to derive an AES-256 key and use the remaining bits as IV (for the encryption).

    Note that the term key stretching is not always used to mean the same thing.