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

RFC: bootutil: Add TLV for Pure (over image) signature #2029

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

de-nordic
Copy link
Collaborator

@de-nordic de-nordic commented Aug 2, 2024

The commit reserves IMAGE_TLV_SIG_PURE == 0x25 as indicator that the signature attached to image is calculated over image rather than its digest (pure, by the name of PureEdDSA). The indicator/flag is provided so that no special TLV is designated to one signature type, because, in theory, any signature algorithm that can be used over image rather than digest can be marked as "Pure".

The PureEdDSA ED25519 signature should be done directly over message, so image in our case. The current implementation is not really PureEdDSA nor HashEdDSA, as we basically pass sha256 as a message to PureEdDSA. Not perfect.

Why is this added?
This PR adds TLV that indicates that PureEdDSA has been run over image rather than sha has been calculated and passed to ed25519 for signature/verification.

Problems
This only works with devices that are mapping flash to RAM address space, so that image signature verification can directly access whole image as message.
This means that configuration with external devices may not work.

Note also that signatures PureEdDSA(image) != PureEdDSA(sha512(image)) != HashEdDSA(sha512(image)), so there is no realu way to use multi-part signature verification with PureEdDSA.

The #2048 is implementation where sha512 is used with PureEdDSA , not perfect.

Copy link
Collaborator

@nvlsianpu nvlsianpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with _PURE ,
think _SHA512 ending would be fine as well.

@d3zd3z
Copy link
Member

d3zd3z commented Sep 9, 2024

The point at the beginning of the description is unclear to me. You state that we are computing a hash of the image, and then using PureEdDSA, and then state that is somehow different from HashEdDSA. I believe that is exactly what HashEdDSA is. You hash the image first, and then use PureEdDSA to sign that hash.

What is your motivation for implementing PureEdDSA. Specifically what cryptographic advantage do we gain here. As far as I can tell, this is to avoid collision resistance of the hash function causing problems with the signature. But we need to be clear here, this is not about natural collision resistance of the hash function (SHA512 would reach a significant collision probability after 2^256 different signatures, this is of a similar order to the number of hydrogen atoms in the visible universe). This is about protecting against vulnerabilities found in the hash function where it becomes possible to generate two documents with the same hash without being able to generate an arbitrary hash. This, for example, is how MD5 failed. However, it wasn't long after than the the robustness of the algorithm collapsed to the point that it was completely vulnerable to even making arbitrary documents with a given hash.

It's arguable that this isn't really the realm of the signature algorithm, and that if a hash function does become vulnerable in this way that we should move away from it as quickly as possible, since if MD5 is any indicator, it is likely to collapse entirely.

But given that most implementations of EdDSA don't seem to be able to work without containing the entire image to be hashed in memory, I see little reason to add this complexity to MCUboot. Even the two-images with the same hash attack this protects against would be difficult to apply here (the same party has to generate both images). It would allow say an independent developer to submit an image for signing to a signing authority, and then deploy a different one with the same signature. However, there isn't any indicator that SHA512 is vulnerable to this, and if it were, there are enough other things that fall apart, it is likely that numerous other means could be used to exploit it as well.

@de-nordic
Copy link
Collaborator Author

The point at the beginning of the description is unclear to me. You state that we are computing a hash of the image, and then using PureEdDSA, and then state that is somehow different from HashEdDSA. I believe that is exactly what HashEdDSA is. You hash the image first, and then use PureEdDSA to sign that hash.

Actually I thought the same but that is not the case. There are differences in HashEd25519 and PureEd25519 implementation (search of phflag https://www.rfc-editor.org/rfc/rfc8032#page-9). I have also experimented with calculating signature with and:

HashEdDSA(sha512(image)) != PureEdDSA(image) != PureEdDSA(sha512(image))

The PureEdDSA(sha512(image)) is what the http://ed25519.cr.yp.to/eddsa-20150704.pdf describes as SHA-512-ED25519-SHA-512.

What is your motivation for implementing PureEdDSA. Specifically what cryptographic advantage do we gain here. As far as I can tell, this is to avoid collision resistance of the hash function causing problems with the signature. But we need to be clear here, this is not about natural collision resistance of the hash function (SHA512 would reach a significant collision probability after 2^256 different signatures, this is of a similar order to the number of hydrogen atoms in the visible universe). This is about protecting against vulnerabilities found in the hash function where it becomes possible to generate two documents with the same hash without being able to generate an arbitrary hash. This, for example, is how MD5 failed. However, it wasn't long after than the the robustness of the algorithm collapsed to the point that it was completely vulnerable to even making arbitrary documents with a given hash.

The only advantage is that there is hardware support that can directly do the signature check on given memory range.
Giving PSA as an example here, you can call psa signature verification giving it access to address space, signature and key id; it will then directly verify signature using key that it takes from some internal storage and all you get is just PSA ret code after operation. No access to hash, no access to key.

It's arguable that this isn't really the realm of the signature algorithm, and that if a hash function does become vulnerable in this way that we should move away from it as quickly as possible, since if MD5 is any indicator, it is likely to collapse entirely.

But given that most implementations of EdDSA don't seem to be able to work without containing the entire image to be hashed in memory, I see little reason to add this complexity to MCUboot. Even the two-images with the same hash attack this protects against would be difficult to apply here (the same party has to generate both images). It would allow say an independent developer to submit an image for signing to a signing authority, and then deploy a different one with the same signature. However, there isn't any indicator that SHA512 is vulnerable to this, and if it were, there are enough other things that fall apart, it is likely that numerous other means could be used to exploit it as well.

Yeah, I agree, on most of above that I understand; even though my over-estimation of usage of sha512 over sha256, regarding security, may not be a good argument in discussion, there is though good point that we have devices that already support hardware accelerated signature processing and they can directly use the "pure" variant of algorithm.
The pure variant can also be directly used in software, although it does not allow usage with external devices, unless there is a way to map them to memory address space.

The PureEdDSA is simpler than the current prehash approach as you do not have to read data by chunk.
There are problems though:

  • will not work with external devices (as mentioned above);
  • the current decrypt-then-verify approach to image signature does not work; you have to carry two signatures - one for encrypted image and one for the "runnable".

@de-nordic de-nordic changed the title RFC: bootutil: Add TLV for correct ED25519 usage RFC: bootutil: Add TLV for ~~correct~~ Pure ED25519 usage Sep 11, 2024
@de-nordic de-nordic changed the title RFC: bootutil: Add TLV for ~~correct~~ Pure ED25519 usage RFC: bootutil: Add TLV for ~correct~ Pure ED25519 usage Sep 11, 2024
@de-nordic de-nordic changed the title RFC: bootutil: Add TLV for ~correct~ Pure ED25519 usage RFC: bootutil: Add TLV for Pure ED25519 usage Sep 11, 2024
@de-nordic
Copy link
Collaborator Author

I think I need to rename the TLV, because there is a way to use other signature algorithms in a "pure" way, and I do not want to mutiply the TVLs.

@de-nordic de-nordic changed the title RFC: bootutil: Add TLV for Pure ED25519 usage RFC: bootutil: Add TLV for Pure (over image) signature Sep 13, 2024
The commit adds SIG_PURE TLV that should be used as TLV indicating
that the signature attached to image has been calculated over
entire image, rather than digest of image.

This is generic flag as the "pure" usage may be applied to, potentially,
any signature algorithm.

Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Encryption support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants