-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add support for EdDSA with ed25519 curve (pure ed25519, ed25519ctx and ed25519ph) #5819
base: development
Are you sure you want to change the base?
Conversation
Largely inspired by the curve25519 definition. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Also tweak mbedtls_ecp_get_type to handle the edwards case. FIXME: there is probably a cleaner way of doing that. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
The RFC8032 recommends to implement ed25519 in extended coordinates and ed448 in projective coordinates. The two coordinates systems are very close with T=x*y for extended coordinates. The corresponding point addition and point doubling formulas are actually very similar. Note that the formulas given in the RFC are the EFD one simplified with a = -1 for ed25519 and a = 1 for ed448. The Mbed TLS philosophy is to share as much code as possible, so projective coordinates are used for both Twisted Edwards and Edwards curves, using the formulas from EFD, which do include the a parameter of the quation. This also matches the mbedtls_ecp_point implementation which supports up to three coordinates. In order to verify EdDSA signatures, it is necessary to add two points. A new mbedtls_ecp_add function is therefore exported in the API. It is only implemented for Edwards curve and returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for other curves. The ecp_check_pubkey function simply checks that the points is on the curve as there are no recommended checks in the RFC8032 nor in the FIPS 186-5 draft. FIXME: There is currently no check for mbedtls_ecp_check_privkey. It's not clear what check should be implemented. FIXME: mbedtls_ecp_set_zero and mbedtls_ecp_is_zero are wrong for Edwards curve, the neutral element being (0, 1). This is not possible to fix that without changing the API as the group parameter is currently not in argument. FIXME: ecp_normalize_edxyz uses a modular inversion. For elliptic curves over GF(p) modular inversions could be done using x^-1 = x^(p-2) (mod p). As it doesn't seem to bring any measureable speed improvement, I kept the modular inversion. FIXME: The mbedtls_ecp_keypair type and the related functions (mbedtls_ecp_gen_key, mbedtls_ecp_read_key, mbedtls_ecp_check_pub_priv) assume that the secret key is a scalar and that the public key is a curve point that is obtained by the scalar multiplication of the base point by the secret key. This is only partially true for the EdDSA algorithm, which employs point enconding and hashes to manipulate those. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es> # Conflicts: # library/ecp.c
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2819b7a
to
58ae415
Compare
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
1 year today. Any new on the progress? |
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Hi Pol, thanks for your help, but unfortunately, given our current commitments, it seems unlikely that we'll have time to review in 2023. At the earliest maybe in the last quarter of 2023, but even that is highly optimistic. |
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
…enates R||s in LE. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
… the error and bypass this param. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Hi. I came across this PR and decided to review it. Note that I'm not associated with mbedtls in any way so the contents of the review are just my personal opinions. APIFirst of all, please have a look at FIPS 186-5 (DSS) where both ECDSA and EdDSA are specified and you will note a very important difference: for ECDSA, inputs and outputs are either (pair of) integers or curve points (except the message hash, which is an octet string), while for EdDSA, all inputs and outputs are octet strings. This applies to private keys, public keys, message/message hashes and signatures. This affects both crypto implementation APIs as well as protocols and certificate standards. You will see that in e.g. TLS, that the ECDSA signatures are "represented as a DER-encode [X690] ECDSA-Sig-Value structure" while EdDSA signatures are simply represented in their standard byte string form, without modifications. In mbedtls, you can see that the ECDSA functions all take mpi integers as inputs/outputs, or the convenience wrapper functions that decode/encode the signature in DER format, while crypto libraries implementing EdDSA use byte arrays as parameters. When reading the proposed API in this PR, I feel it's a bit too much of a copy-paste from the ECDSA API:
Other comments:
There is an earlier comment here that references An EdDSA signature implementation is unsafe if it allows a different public key to be used. Let me give some of my comments on that. The issue arises when a signer signs the same message twice, using the same private key but incorrectly passes the wrong public key to the sign function at least one of the times, so that the public keys differ in the two signing operations. The two resulting signatures will share the same R but have different S. An attacker that sees these two signatures as well as the two different public keys used can immediately derive the private key (or actually the first half of the hash of the private key, which is enough to create forged signatures). The probabilities for this to happen in the real world sounds to me pretty low. Firstly, the protocol that uses Ed25519 sign must allow the same message to be signed twice. Secondly, the software must either be buggy (passing the incorrect public key), or the sign operation is a manual one where a user inputs the (incorrect) private/public key pair. For TLS, this will not happen for CertificateVerify, since the sender's random value will be different every time, which is part of the message to be hashed. The original Ed25519 paper defines a private key to be 32 bytes and a public key to be 32 bytes, but does not really define any APIs for signing/verifying. It instead simply documents that their reference software assumes that the public key is already computed at the time a sign operation is to be performed. The API in the reference software uses a 64 bytes long byte array as private key, containing a concatenation of the private key and the public key. RFC 8032 defines a "procedure" for signing. Here, the only inputs to that procedure are the private key (32 bytes) and the message; the public key is derived from the private key as the first step of the sign procedure. FIPS 186-5 defines the signature generation process in a different way. Here, the inputs are the message and the "valid" private-public key pair, i.e. the public key is assumed to be pre-computed. Now, that GitHub repository above shows a "blacklist"/"wall of shame" of libraries implementing the API in FIPS 186-5, where the public-private keypair is passed split up using two parameters. I think that is a bit too harsh. If anything, they should blame the standard FIPS 186-5 and not the libraries implementing this standard. Anyway, there are a few "solutions" to the "problem":
For mbedtls, I think the first option is out of the question since it is important to have efficient implementations in embedded systems. ImplementationI can see in the previous discussion that there are of course different approaches for carrying out the scalar multiplications that all have tradeoffs between code size/RAM usage/time/reusability with e.g. X25519. I would like to join that discussion too. Note that a big motivation/reason for using Ed25519 over ECDSA is the possibility to get better performance. So, an implementation that is slower than ECDSA, for the same security level, would not be well received. Mbedtls already has some fancy comb implementation for ECDSA which on a high level is pretty good. The proposed Montgomery ladder in this PR, using the generic Edwards curve formulae, not optimized for Twisted Edwards curves, and not optimized for a=-1, with a double-add strategy for every bit, taking in total 21M per bit for base point multiplication, is probably the slowest possible way to implement Ed25519. The "standard" Montgomery ladder, using the Montgomery curve, instead uses 9M per bit. As has been mentioned previously, it can even share code with X25519/X448. I would say it is worth the effort to use this approach instead, whatever modifications that are needed in the current Montgomery curve ladder to make this possible. And even better, use a comb method like how it's done for ECDSA, to actually be able to beat ECDSA in speed. If space is a concern, even a comb implementation that processes two bits at a time would be faster than the Montgomery curve ladder and would require only 2 pre-computed points Using "Shamir's trick" is a quite decent choice though for double scalarmult, instead of performing two generic multiplications and then adding the results. The signed wNAF approach in the ref10 implementation is however ~30% faster but needs to store 8 points in a table in RAM, so I think that algorithm is a good candidate as well. In any case, you should really consider the Twisted Edwards Curve formulae optimized for a=-1 to achieve 7M per point double operation and 8M per point add operation, instead of 8M and 13M as it is right now. Now to bugs:
|
Mbed TLS 3.5.0 Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
Description
It adds support for EdDSA with Ed25519 curve (sign and verify).
Ed448 curve will be added in a separated PR.
Splitted from #5800.
Status
READY
Requires Backporting
NO
Migrations
NO
Additional comments
Any additional information that could be of interest
Todos