| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
one question: should we put an assertion to check the out_len after EVP_CipherUpdate() and see if it exceeds the original allocated size? |
Sorry, something went wrong.
|
@yhwang I think that makes sense, yes. 👍 /cc @nodejs/crypto |
Sorry, something went wrong.
|
Is there no 3DES support in Node 9? I tried the test in Node 9 and it threw Error: Unknown cipher. |
Sorry, something went wrong.
Sorry, something went wrong.
|
@addaleax Let me do it. thanks @ryzokuken does it means that I should label this with dont-land-v9.x and others? |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM as a fix.
Sorry, something went wrong.
|
Marking this as security as I wrote a report for the Node.js security team a couple of days ago. An attacker can - hypothetically - write eight bytes into (un)allocated heap and at least partially control their contents. |
Sorry, something went wrong.
|
@yhwang I think @tniessen and @addaleax would know better. AFAIK, 3des-wrap was introduced in Node.js 10 (it throws with unknownCipher in Node.js 6, 8 and 9), so, yeah. It should be semver-patch (because it throws on Node.js 10 with): ~/Code/temp/node
❯ node crypto.js
node(79558,0x7fffa1d72380) malloc: *** error for object 0x10250fd60: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
[1] 79558 abort node crypto.jsbut yeah, label it so that it doesn't land on Node.js 6, 8 and 9 (if 3des-wrap is the only cipher this one applies on, though). I hope this clarifies everything. |
Sorry, something went wrong.
|
I mean, the dont-land labels depend on a couple factors – as in, what is the negative impact if we do merge this to an LTS line? Does it make backporting there easier? The only downside I can think of is slightly higher memory consumption, but as I understand it these chunks are not all that large to begin with. Plus, we could reduce that problem by doing a shrinking Realloc() call in case of success, I guess? |
Sorry, something went wrong.
There was a problem hiding this comment.
The bug is that key wrap algorithms overflow because of the envelope that's added?
Allocating double the block size doesn't look Obviously Correct to me as the envelope size has no direct relationship to the block size.
The reason this PR fixes the immediate issue is because openssl currently only supports AES and 3DES key wrap modes, where envelope size == block size by happenstance.
I think a better solution is to check first if EVP_CIPHER_mode(cipher) == EVP_CIPH_WRAP_MODE and then check the NID against a whitelist with EVP_CIPHER_nid(cipher) and throw an exception when we don't recognize it.
You can look up the NIDs with grep wrap deps/openssl/openssl/crypto/objects/obj_dat.h | grep NID but note that some ciphers are disabled in our builds so you probably want to intersect with node -p 'crypto.getCiphers().filter(s => s.toLowerCase().includes("wrap"))'.
Ideally, each whitelisted cipher should have a test case to make sure it's working as expected.
Sorry, something went wrong.
There was a problem hiding this comment.
I'd use fixed strings to keep the test deterministic.
Sorry, something went wrong.
|
@bnoordhuis I was thinking the same thing, but a better solution can still be implemented later on. This patch at least makes sure that we don't overwrite unallocated heap memory. (And yes, the connection between envelope size and blocksize is debatable.) |
Sorry, something went wrong.
|
I can live with that but I'd suggest the following:
That way there can be no hidden footguns or time bombs. @yhwang Ping me if you have questions or want help. |
Sorry, something went wrong.
|
I want to say: I love your comments and I will update my change according to your comments. @bnoordhuis I will ping you if I need help. I have a family event this weekend and will be back to this next Tuesday. I will do the change then. |
Sorry, something went wrong.
I am not sure if it's the envelope. Based on the spec it's the sha1 of the key: https://tools.ietf.org/html/rfc3217#section-2 For the key wrap algorithms, seems you can call EVP_CipherUpdate() and pass nullptr for the out parameter. Then it will return you the proper size you need to allocate. Should we do that?
It shouldn't be specific to key wrap algorithms. We should do the check for the algorithms that we supports, right? |
Sorry, something went wrong.
If that works, that would be great, but I couldn't find a conclusive solution in the documentation. |
Sorry, something went wrong.
|
@tniessen I can't find documentation either. I read the logic in aes_wrap_cipher() and des_ede3_wrap_cipher(). And in cms_kek_cipher(), it calls EVP_CipherUpdate() with null output to obtain output length. |
Sorry, something went wrong.
|
@tniessen I updated the change to get output length before memory allocation. @bnoordhuis please let me know should I add CHECK for key wrapping? (my question is should we do the CHECK for all supported algorithms but not only for key wrapping? If that's the case, should I do it separately?) For aes128-wrap, aes192-wrap and aes254-wrap, can I add test cases for these algorithms later in another PR? |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM assuming you checked the returned value manually and CI passes. I'd still prefer to see this behavior of EVP_CipherUpdate documented just so we don't rely on undefined behavior, but that's probably beyond our power.
Sorry, something went wrong.
There was a problem hiding this comment.
Nit: Period at the end of the sentence.
Sorry, something went wrong.
There was a problem hiding this comment.
@tniessen fixed. Thanks!
Sorry, something went wrong.
That's 3DES. AES is different: https://tools.ietf.org/html/rfc3394#page-4. I use 'envelope' as a catch-all for the key wrap data that's added.
I think they're the only ones that add extra data. But if there's a reliable generic way of detecting that upfront, so much the better. |
Sorry, something went wrong.
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com>
Sorry, something went wrong.
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com> PR-URL: #20370 Fixes: #19655 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com> PR-URL: #20370 Fixes: #19655 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
|
Back-porters, this should land along with #20587. |
Sorry, something went wrong.
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com> PR-URL: #20370 Fixes: #19655 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com> PR-URL: nodejs#20370 Fixes: nodejs#19655 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
For key wrapping algorithms, calling EVP_CipherUpdate() with null output could obtain the size for the ciphertext. Then use the returned size to allocate output buffer. Also add a test case to verify des3-wrap. Signed-off-by: Yihong Wang <yh.wang@ibm.com> Backport-PR-URL: #20706 PR-URL: #20370 Fixes: #19655 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
| Back | FazBrowse Home | New Git URL |
For some algorithms, they need extra 2x blocksize to store the ciphertext in
order to avoid invalid write. Also add a test case to verify it.
refs: #19655
Signed-off-by: Yihong Wang yh.wang@ibm.com
Checklist