mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
src,crypto: fix 0-length output crash in webcrypto
Fixes: https://github.com/nodejs/node/issues/38883 PR-URL: https://github.com/nodejs/node/pull/38913 Refs: https://github.com/nodejs/node/issues/38883 Reviewed-By: Tobias Nießen <tniessen@tnie.de>
This commit is contained in:
1 parent
b3d4a2ca82
commit
8954e03ad9
3 files changed
+55
-5
No files matched your search
@@ -130,7 +130,17 @@ WebCryptoCipherStatus AES_Cipher(
|
||||
ByteSource buf = ByteSource::Allocated(data, buf_len);
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
|
||||
|
||||
if (!EVP_CipherUpdate(
|
||||
// In some outdated version of OpenSSL (e.g.
|
||||
// ubi81_sharedlibs_openssl111fips_x64) may be used in sharedlib mode, the
|
||||
// logic will be failed when input size is zero. The newly OpenSSL has fixed
|
||||
// it up. But we still have to regard zero as special in Node.js code to
|
||||
// prevent old OpenSSL failure.
|
||||
//
|
||||
// Refs: https://github.com/openssl/openssl/commit/420cb707b880e4fb649094241371701013eeb15f
|
||||
// Refs: https://github.com/nodejs/node/pull/38913#issuecomment-866505244
|
||||
if (in.size() == 0) {
|
||||
out_len = 0;
|
||||
} else if (!EVP_CipherUpdate(
|
||||
ctx.get(),
|
||||
ptr,
|
||||
&out_len,
|
||||
|
||||
@@ -249,16 +249,17 @@ class CipherJob final : public CryptoJob<CipherTraits> {
|
||||
v8::Local<v8::Value>* result) override {
|
||||
Environment* env = AsyncWrap::env();
|
||||
CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors();
|
||||
if (out_.size() > 0) {
|
||||
|
||||
if (errors->Empty())
|
||||
errors->Capture();
|
||||
|
||||
if (out_.size() > 0 || errors->Empty()) {
|
||||
CHECK(errors->Empty());
|
||||
*err = v8::Undefined(env->isolate());
|
||||
*result = out_.ToArrayBuffer(env);
|
||||
return v8::Just(!result->IsEmpty());
|
||||
}
|
||||
|
||||
if (errors->Empty())
|
||||
errors->Capture();
|
||||
CHECK(!errors->Empty());
|
||||
*result = v8::Undefined(env->isolate());
|
||||
return v8::Just(errors->ToException(env).ToLocal(err));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto').webcrypto;
|
||||
|
||||
(async () => {
|
||||
const k = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
new Uint8Array(32),
|
||||
{ name: 'AES-GCM' },
|
||||
false,
|
||||
[ 'encrypt', 'decrypt' ]);
|
||||
assert(k instanceof crypto.CryptoKey);
|
||||
|
||||
const e = await crypto.subtle.encrypt({
|
||||
name: 'AES-GCM',
|
||||
iv: new Uint8Array(12),
|
||||
}, k, new Uint8Array(0));
|
||||
assert(e instanceof ArrayBuffer);
|
||||
assert.deepStrictEqual(
|
||||
Buffer.from(e),
|
||||
Buffer.from([
|
||||
0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
|
||||
0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b ]));
|
||||
|
||||
const v = await crypto.subtle.decrypt({
|
||||
name: 'AES-GCM',
|
||||
iv: new Uint8Array(12),
|
||||
}, k, e);
|
||||
assert(v instanceof ArrayBuffer);
|
||||
assert.strictEqual(v.byteLength, 0);
|
||||
})().then(common.mustCall()).catch((e) => {
|
||||
assert.ifError(e);
|
||||
});
|
||||
Reference in new issue
Block a user