PKCS12 KDF + MD2 incorrect result
guidovranken opened this issue · 5 comments
Parameters:
digest: MD2
password: {0x81} (1 bytes)
salt: {0x01} (1 bytes)
iterations: 1
keySize: 88
mbed TLS produces:
{0xde, 0x5a, 0xee, 0xcf, 0x1f, 0xbf, 0x8b, 0x7f, 0xc0, 0xa2, 0x90, 0xc3, 0xbf, 0x24, 0xc0, 0x7a,
0xa3, 0xd8, 0x0f, 0x2a, 0x42, 0xab, 0x3b, 0x8b, 0x6d, 0xae, 0xb1, 0xcf, 0xf4, 0x9e, 0x99, 0xf1,
0x3c, 0x89, 0x3b, 0xb6, 0x82, 0xbf, 0xf9, 0x15, 0x2e, 0x65, 0x81, 0xc0, 0x52, 0x9f, 0x39, 0x8e,
0x28, 0x90, 0x11, 0x49, 0x4f, 0x7c, 0x9c, 0xb7, 0x97, 0xed, 0xcb, 0x1a, 0x73, 0x59, 0xa4, 0x98,
0xef, 0xff, 0x6f, 0xb9, 0xaa, 0x5a, 0x2c, 0xbe, 0xc7, 0x59, 0x5c, 0x5e, 0xcf, 0xe1, 0x44, 0x3b,
0x66, 0x25, 0x5a, 0xca, 0xdd, 0xce, 0x79, 0x5f} (88 bytes)
Both libtomcrypt and Crypto++ produce:
{0xb1, 0xba, 0xcd, 0x02, 0x85, 0x8b, 0xfa, 0x52, 0xab, 0x0b, 0x35, 0x92, 0xb3, 0xc1, 0x8b, 0x38,
0x81, 0xa9, 0x7d, 0x59, 0x13, 0x6f, 0x30, 0x43, 0x5f, 0x04, 0x95, 0xc3, 0x08, 0x9d, 0x2a, 0x87,
0x19, 0xfb, 0xd4, 0x05, 0x2d, 0xc1, 0xe3, 0x5b, 0x4e, 0x78, 0x6b, 0x2e, 0xb6, 0x41, 0x75, 0xa5,
0x03, 0xab, 0x83, 0x68, 0xa2, 0xff, 0xd2, 0x02, 0x5a, 0x9b, 0x4a, 0xe8, 0xe5, 0x3d, 0xcb, 0xbd,
0xe9, 0x67, 0x2f, 0xb9, 0x6d, 0xba, 0xbb, 0x62, 0x71, 0xcb, 0x72, 0x29, 0x20, 0xf7, 0xec, 0x14,
0x9c, 0xfc, 0xf8, 0xd8, 0x9a, 0x50, 0x61, 0x45} (88 bytes)
So I am assuming the mbed TLS output is incorrect.
A discrepancy only occurs with PKCS12 KDF + MD2, not any other hash functions.
This is how I invoke PKCS12 KDF in mbed TLS: https://github.com/guidovranken/cryptofuzz/blob/f1b8e13c1dfd695da0f15268ffe99d4b0ae7ef64/modules/mbedtls/module.cpp#L734-L743
Thanks for the report! It seems a bit puzzling that the discrepancy occurs only with MD2 and no other hash function. By any chance, did you investigate or have any idea why that might be?
Unfortunately I haven't looked at the cause, however I can say that MD2 in mbed TLS works correctly as a digest, as a HMAC, and as a HKDF and a PBKDF2.
This intrigued me, so I looked at what could be special about MD2. PKCS#12 states:
Let H be a hash function built around a compression function f: Z2u × Z2v → Z2u (that is, H has a chaining variable and output of length u bits, and the message input to the compression function of H is v bits). For MD2 and MD5, u=128 and v=512; for SHA-1, u=160 and v=512.
RFC 7292 has similar language.
The specification is inconsistent: the size of the message input to the compression function is 128 bits, not 512 bits. Mbed TLS uses the explicit value stated in the specification, but most other implementations follow the generic rule of using the block size.
I verified on https://github.com/gilles-peskine-arm/mbedtls/tree/pkcs12-md2 that changing to use the block size causes Mbed TLS to produce the same output as libtomcrypt and crypto++. (The patch in that branch is probably not what we want: we should probably use md_info->block_size
, which would also fix SHA-512/256 if we add it one day.)
@guidovranken Did you find any other implementation that produces the same output as Mbed TLS?
@guidovranken Did you find any other implementation that produces the same output as Mbed TLS?
In my fuzzer the only other libraries that support PKCS12 KDF are wolfCrypt and OpenSSL.
wolfCrypt doesn't support PKCS12 KDF + MD2.
OpenSSL 1.1.1k produces the same result as Crypto++ and libtomcrypt.
On a related note, it might interest you that there are two interpretations of the DES-X cipher: openssl/openssl#9703 (comment)