-
Notifications
You must be signed in to change notification settings - Fork 106
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
DESFire key diversification does not agree with AN10922 #91
Comments
:( It is unfortunately too late for me, since I already have cards deployed with the wrong (possibly less secure?) derivation function. |
Untested code for correcting cmac(), so mifare_derive_key can pass buffer manually padded to correct length for key but the crypto commands can still use default padding.
|
@dodgambit, thank you for this details report! I guess the best response to be done is to fix this problem is:
|
Well crap. I implemented all of the relevant test vectors from AN10922, and they all passed. It seems that AN10922 didn't include any test vectors with less than one block. The absence of test vectors for 8 bytes or less of diversification data is going to make it difficult to positively confirm that a new version of the diversification is, in fact, correct. CMAC, when used with AES-128, is secure with only a single message block. I have no idea why they expand it to two for AN10922. CMAC comes with a robust security proof, AN10922 doesn't, so if anything I'd call what was implemented more secure, not less secure. That being said, I don't see any reason why the AN10922 version would actually be less secure, but not using cryptographic primitives exactly as specified is never a good idea. In other words, I don't think you should worry that what you are using is less secure. It is as secure as CMAC, which has a security proof. Doing an extra round of crypto on padding doesn't increase the security. I designed the API so that it would be possible to have different constructors for different diversification algorithms. We could simply have a What a shame. This could have all been avoided with better test vectors in AN10922. |
My initial plan is to deprecate But there is a bigger problem, and I've already mentioned it:
This seems like a big deal. I could add support for this and just go with the numbers I end up getting and hope I'm correct, but I think @smortex would frown on that. I suppose I could just try to be super careful. It's a shame that AN10922 didn't include a larger test vector corpus. @dodgambit, if you don't mind me asking, how did you come to determine this deficiency? Was it a code review, or did you actually encounter a case where the keys didn't match up? |
Actually, thinking more about it, adding some sort of flags parameter to |
It looks like there might be a suitable "official" test vector for the short case in AN10957, pages 13-14:
This gives at least allows us to know if the fix is correct. |
This commit fixes issue nfc-tools#91. [AN10922][] specifies the key diversification algorithms used by the MIFARE SAM AV3. Support for these algorithms was added to `libfreefare` via pull-request nfc-tools#79. However, while every attempt was made to write a faithful implementation, the implemented code did not properly handle cases where the diversification data was less than or equal to 2x the block size of the cipher: 16 bytes for AES, and 8 bytes for DES. This bug was identified in issue nfc-tools#91. This commit addresses this problem while providing a way to revert to the previous behavior in cases where it is necessary to maintain previous deployments. This was accomplished by introducing a new `flags` parameter to the `mifare_key_deriver_new_an10922` method. Normally, `flags` should simply be set to `AN10922_FLAG_DEFAULT`. However, if the previous behavior is required, it should be set to `AN10922_FLAG_EMULATE_ISSUE_91`. [AN10922][] does not include any test vectors that might have helped to identify this problem earlier. However, [AN10957][] (pages 13-14) was found to have a suitable example usage of [AN10922][] with an appropriately short value for *M* that we are using as a test vector to verify correct behavior. Note that the issue being addressed here is not a security issue: using the `AN10922_FLAG_EMULATE_ISSUE_91` should not be any less secure than using `AN10922_FLAG_DEFAULT`. [AN10922]: https://www.nxp.com/docs/en/application-note/AN10922.pdf [AN10957]: https://www.nxp.com/docs/en/application-note/AN10957.pdf
This commit fixes issue nfc-tools#91. [AN10922][] specifies the key diversification algorithms used by the MIFARE SAM AV3. Support for these algorithms was added to `libfreefare` via pull-request nfc-tools#79. However, while every attempt was made to write a faithful implementation, the implemented code did not properly handle cases where the diversification data was less than or equal to the block size of the cipher: 16 bytes for AES, and 8 bytes for DES. This bug was identified in issue nfc-tools#91. This commit addresses this problem while providing a way to revert to the previous behavior in cases where it is necessary to maintain previous deployments. This was accomplished by introducing a new `flags` parameter to the `mifare_key_deriver_new_an10922` method. Normally, `flags` should simply be set to `AN10922_FLAG_DEFAULT`. However, if the previous behavior is required, it should be set to `AN10922_FLAG_EMULATE_ISSUE_91`. [AN10922][] does not include any test vectors that might have helped to identify this problem earlier. However, [AN10957][] (pages 13-14) was found to have a suitable example usage of [AN10922][] with an appropriately short value for *M* that we are using as a test vector to verify correct behavior. Note that the issue being addressed here is not a security issue: using the `AN10922_FLAG_EMULATE_ISSUE_91` should not be any less secure than using `AN10922_FLAG_DEFAULT`. [AN10922]: https://www.nxp.com/docs/en/application-note/AN10922.pdf [AN10957]: https://www.nxp.com/docs/en/application-note/AN10957.pdf
This commit fixes issue nfc-tools#91. [AN10922][] specifies the key diversification algorithms used by the MIFARE SAM AV3. Support for these algorithms was added to `libfreefare` via pull-request nfc-tools#79. However, while every attempt was made to write a faithful implementation, the implemented code did not properly handle cases where the diversification data was less than or equal to the block size of the cipher: 16 bytes for AES, and 8 bytes for DES. This bug was identified in issue nfc-tools#91. This commit addresses this problem while providing a way to revert to the previous behavior in cases where it is necessary to maintain previous deployments. This was accomplished by introducing a new `flags` parameter to the `mifare_key_deriver_new_an10922` method. Normally, `flags` should simply be set to `AN10922_FLAG_DEFAULT`. However, if the previous behavior is required, it should be set to `AN10922_FLAG_EMULATE_ISSUE_91`. [AN10922][] does not include any test vectors that might have helped to identify this problem earlier. However, [AN10957][] (pages 13-14) was found to have a suitable example usage of [AN10922][] with an appropriately short value for *M* that we are using as a test vector to verify correct behavior. Note that the issue being addressed here is not a security issue: using the `AN10922_FLAG_EMULATE_ISSUE_91` should not be any less secure than using `AN10922_FLAG_DEFAULT`. [AN10922]: https://www.nxp.com/docs/en/application-note/AN10922.pdf [AN10957]: https://www.nxp.com/docs/en/application-note/AN10957.pdf
This commit fixes issue nfc-tools#91. [AN10922][] specifies the key diversification algorithms used by the MIFARE SAM AV3. Support for these algorithms was added to `libfreefare` via pull-request nfc-tools#79. However, while every attempt was made to write a faithful implementation, the implemented code did not properly handle cases where the diversification data was less than or equal to the block size of the cipher: 16 bytes for AES, and 8 bytes for DES. This bug was identified in issue nfc-tools#91. This commit addresses this problem while providing a way to revert to the previous behavior in cases where it is necessary to maintain previous deployments. This was accomplished by introducing a new `flags` parameter to the `mifare_key_deriver_new_an10922` method. Normally, `flags` should simply be set to `AN10922_FLAG_DEFAULT`. However, if the previous behavior is required, it should be set to `AN10922_FLAG_EMULATE_ISSUE_91`. [AN10922][] does not include any test vectors that might have helped to identify this problem earlier. However, [AN10957][] (pages 13-14) was found to have a suitable example usage of [AN10922][] with an appropriately short value for *M* that we are using as a test vector to verify correct behavior. Note that the issue being addressed here is not a security issue: using the `AN10922_FLAG_EMULATE_ISSUE_91` should not be any less secure than using `AN10922_FLAG_DEFAULT`. [AN10922]: https://www.nxp.com/docs/en/application-note/AN10922.pdf [AN10957]: https://www.nxp.com/docs/en/application-note/AN10957.pdf
Fixed by #118. |
mifare_key_deriver does not compute the right diversified key when the input is less than the key block size.
This problem will be very common for something like UID-based diversification, since the UID will always be less than the key block size.
For example, AN10922 specifies that the input data for AES128 key diversification input must consist of exactly 32 bytes: 0x01 | M | Padding.
However, if M is, say, 7 bytes long, mifare_key_deriver_end_raw() will only pass 8 bytes (0x01 | M) to the libfreefare cmac() function, which will pad that input to 16 bytes and compute the CMAC of just those 16 bytes.
According to AN10922, the input should have been padded to 32 bytes, so that 2 encryptions are done, flowing through the IV, presumably producing a "more encrypted" or "more difficult to reverse" result.
There is no way to tell the existing cmac() function to pad to 32 bytes in this case when the input is less than 16 bytes. This is only a problem with key diversification -- cmac() pads just fine when computing the CMAC for a secure channel.
Solutions:
The text was updated successfully, but these errors were encountered: