-
Notifications
You must be signed in to change notification settings - Fork 1.7k
The ECDH and X25519 deriveBits returns an empty string when 'length' is 0 #31146
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
The ECDH and X25519 deriveBits returns an empty string when 'length' is 0 #31146
Conversation
|
EWS run on previous version of this PR (hash 79ccd0e) |
79ccd0e to
9af3f2c
Compare
|
EWS run on previous version of this PR (hash 9af3f2c) |
9af3f2c to
a66c770
Compare
|
EWS run on previous version of this PR (hash a66c770) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This technically does work. But I think it would be wise to check for null as the first thing in the function ::deriveBits and bail early.
For Zero, I think we can check right before this lambda and don't even get into doing scalar multiplication and just return a zero length result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on the optimization for the zero length, which would even allow us to avoid the call to the platformDeriveBits key.
However I'm not so sure about the early bail in case of null; since the change to define length as optional, null means that we should return the full derivedKey. Hence, I don't think we save much to avoid doing the check inside the lambda.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, not a strong opinion, but I think it's better to do the length = 0 after the rest of the basic checks (eg. ec parameters, key type, algorithm name). Otherwise we would hide failures in those checks when passing 0 as length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise we would hide failures in those checks when passing 0 as length.
It's true vice versa. If we were adding those other checks in this PR instead of zero length, do you think the same argument applies ? I might be missing stuff in the spec. I had a quick look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional, null means that we should return the full derivedKey.
I did not know that. Then I guess we need to derive the key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise we would hide failures in those checks when passing 0 as length.
It's true vice versa. If we were adding those other checks in this PR instead of zero length, do you think the same argument applies ? I might be missing stuff in the spec. I had a quick look.
Very true; my preference is based on the fact that the 'length' behavior is based on the specific algorithm ; for instance, PBKDF2 and HKDF would throw in case of 0, and we are aiming for ECDH and X25519 to throw on any truncation. So in my mind it makes more sense to ensure first that the algorithm name, key type and usages are validates and only then check the specific values of the 'length' parameter.
But as I said, I don't have a strong opinion on this, because you have a valid point and perhaps it's more efficient to early return based on an "cheap" check of the length's value, avoiding the other checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does work technically but with the spec change the code can be easily made a little better at failing or returning fast.
a66c770 to
e6ce092
Compare
|
EWS run on previous version of this PR (hash e6ce092) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit:
| if (length && !(*length)) { | |
| if (!length.value_or(0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not correct; we would return an empty string in case "null". The spec states:
If length is null:
Return secret
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ohh. right.. then what you have is perfect.
To re-state, Truncate only if length is explicitly provided!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the work on this PR and the spec!
e6ce092 to
7c8d375
Compare
|
EWS run on current version of this PR (hash 7c8d375) |
|
Commit message contains (OOPS!) and Nitin Mahendru is not a reviewer, blocking PR #31146. Details: Build #15819 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this test cases for 256 bits, and similar below, not valuable anymore? How does that relate to the 0-length check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this test cases for 256 bits, and similar below, not valuable anymore? How does that relate to the 0-length check?
The test case checked that when passing 0 as 'length', the result was the full string; now we should return an empty string instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes lgtm.
…is 0 https://bugs.webkit.org/show_bug.cgi?id=276916 Reviewed by Matthew Finkel. The WebCrypto API spec's draft states that the ECDH's deriveBits should handle a zero length as any regular number, only throwing an exception in case of 'null'. The same is stated in the Secure Curves specification draft for the X25519 algorithm. We were not supporting 'null' value before, but since r281240 the 'length' parameter is defined as optional, with 'null' as default value. Hence in case of a zero length the derived bits are truncated so that the operation returns an empty string. * LayoutTests/crypto/subtle/ecdh-derive-bits-length-limits-expected.txt: * LayoutTests/crypto/subtle/ecdh-derive-bits-length-limits.html: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any.worker-expected.txt: * Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.cpp: (WebCore::CryptoAlgorithmECDH::deriveBits): * Source/WebCore/crypto/algorithms/CryptoAlgorithmX25519.cpp: (WebCore::CryptoAlgorithmX25519::deriveBits): Canonical link: https://commits.webkit.org/285383@main
7c8d375 to
0b46039
Compare
|
Committed 285383@main (0b46039): https://commits.webkit.org/285383@main Reviewed commits have been landed. Closing PR #31146 and removing active labels. |
0b46039
7c8d375