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

Add support for Ed25519 to NativeCrypto #1287

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

juergw
Copy link
Contributor

@juergw juergw commented Jan 9, 2025

BoringSSL doesn't support Ed25519 with EVP_DigestUpdate, only with EVP_DigestSign and EVP_DigestVerify. So we need to add wrappers of these functions to NativeCrypto.

juergw added 2 commits January 9, 2025 15:47
BoringSSL doesn't support Ed25519 with EVP_DigestUpdate, only
with EVP_DigestSign and EVP_DigestVerify. So we need to add wrappers
of these functions to NativeCrypto.
@juergw
Copy link
Contributor Author

juergw commented Jan 9, 2025

Test org.conscrypt.java.security.cert.X509CertificateTest.utcTimeWithOffset fails. I don't see how this is related to my changes.

@prbprbprb
Copy link
Collaborator

Yeah, that's a BoringSSL change, I'll ping them.

Comment on lines +2802 to 2803
if (md == nullptr && (EVP_PKEY_id(pkey) != EVP_PKEY_ED25519)) {
JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
Copy link
Collaborator

Choose a reason for hiding this comment

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

n00b question: Why is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For all other key types, md must not be null. But for Ed25519, it must always be null, see:

https://docs.openssl.org/3.0/man7/EVP_SIGNATURE-ED25519/#ed25519-and-ed448-signature-parameters
or
https://github.com/google/boringssl/blob/master/include/openssl/evp.h#L239

Maybe I should make this check stronger, and reject a non-null md for ed25519.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Understood. Maybe just add a comment so the next person along understands :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also raises the question of what we do in SignatureSpi... Have update() cache the data and do a one-shot operation on sign() or verify(), I guess?

Copy link
Collaborator

@prbprbprb prbprbprb left a comment

Choose a reason for hiding this comment

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

Overall LGTM but I want to re-check my working later on a couple of bits and maybe ask davidben to give it a quick once over in case we're missing anything on the BoringSSL side.

@davidben
Copy link
Contributor

Is the intention to then call this from the higher level Java bits, just in a separate PR? (My understanding was that NativeCrypto was not public API in Conscrypt.)

@prbprbprb
Copy link
Collaborator

Is the intention to then call this from the higher level Java bits, just in a separate PR? (My understanding was that NativeCrypto was not public API in Conscrypt.)

Exactly! Next steps would would be to wire up Java implementations of KeyPairGeneratorSpi, KeyFactorySpi, SignatureSpi etc - also not public APIs and probably using private (to Conscrypt) Key classes as we did for X25519. And finally expose it (when ready) as a public API via OpenSSLProvider.

Further down the road we should make this (and X25519) able to use the RI interface and key classes, but there's a whole conditional compilation issue there as those classes don't exist on many of the platforms we need to support.

Comment on lines +2802 to 2803
if (md == nullptr && (EVP_PKEY_id(pkey) != EVP_PKEY_ED25519)) {
JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also raises the question of what we do in SignatureSpi... Have update() cache the data and do a one-shot operation on sign() or verify(), I guess?


size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not this CL but we should add a method for this as it gets thrown in a many places so we might as well cache the class.


if (outPublic.size() != ED25519_PUBLIC_KEY_LEN) {
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
"Output public key array length != 32");
Copy link
Collaborator

Choose a reason for hiding this comment

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

conscrypt::jniutil::throwIllegalArgumentException()

}

if (outPrivate.size() != ED25519_PRIVATE_KEY_LEN) {
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants