Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKCS12 KDF + MD2 incorrect result #4267

Open
guidovranken opened this issue Mar 30, 2021 · 5 comments
Open

PKCS12 KDF + MD2 incorrect result #4267

guidovranken opened this issue Mar 30, 2021 · 5 comments
Labels
bug size-s Estimated task size: small (~2d)

Comments

@guidovranken
Copy link
Contributor

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

@mpg
Copy link
Contributor

mpg commented Mar 31, 2021

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?

@guidovranken
Copy link
Contributor Author

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.

gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this issue Mar 31, 2021
PKCS#12 explicitly specifies that v = 512 bits = 64 bytes for MD2,
corresponding to the width of the compression function that it uses
internally. However, most implementations of PKCS#12 use
v = 128 bits = 16 bytes, corresponding to the amount of input that
gets processed by one iteration of the compression function. MD2
is the only common hash function for which these two quantities
are different. Mbed TLS classically used the value from the standard,
but this made it incompatible with the rest of the world.

Fix Mbed-TLS#4267.

Signed-off-by: Gilles Peskine <[email protected]>
gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this issue Mar 31, 2021
PKCS#12 explicitly specifies that v = 512 bits = 64 bytes for MD2,
but this is an incorrect application of the general rule of using the
size of "the message input to the compression function", i.e. the
block size, which is 128 bits = 16 bytes.

Mbed TLS classically used the explicit value from the specification,
but this made it incompatible with the rest of the world, so change to
follow the generic rule from the specification, which is also the de
facto standard.

Fix Mbed-TLS#4267.

Signed-off-by: Gilles Peskine <[email protected]>
@gilles-peskine-arm
Copy link
Contributor

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
Copy link
Contributor Author

@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.

@guidovranken
Copy link
Contributor Author

On a related note, it might interest you that there are two interpretations of the DES-X cipher: openssl/openssl#9703 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug size-s Estimated task size: small (~2d)
Projects
None yet
Development

No branches or pull requests

6 participants