summaryrefslogtreecommitdiff
path: root/test/known_issues
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2020-02-18 12:26:49 +0100
committerAnna Henningsen <anna@addaleax.net>2020-04-02 18:00:07 +0200
commit6f942218848c7f5993f86bdcbd299b0fd73749d9 (patch)
tree50a2a50008eb7a9f3d4719d651ccc46385218951 /test/known_issues
parente06512b9b75552f73371512ded879e472c0ec57e (diff)
downloadnode-new-6f942218848c7f5993f86bdcbd299b0fd73749d9.tar.gz
test: add known issues test for #31733
Authenticated decryption works for file streams up to 32768 bytes but not beyond. Other streams and direct decryption are not affected. Refs: https://github.com/nodejs/node/issues/31733 PR-URL: https://github.com/nodejs/node/pull/31734 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'test/known_issues')
-rw-r--r--test/known_issues/test-crypto-authenticated-stream.js142
1 files changed, 142 insertions, 0 deletions
diff --git a/test/known_issues/test-crypto-authenticated-stream.js b/test/known_issues/test-crypto-authenticated-stream.js
new file mode 100644
index 0000000000..1e2a9edd7b
--- /dev/null
+++ b/test/known_issues/test-crypto-authenticated-stream.js
@@ -0,0 +1,142 @@
+/* eslint-disable node-core/crypto-check */
+'use strict';
+// Refs: https://github.com/nodejs/node/issues/31733
+const common = require('../common');
+const assert = require('assert');
+const crypto = require('crypto');
+const fs = require('fs');
+const path = require('path');
+const stream = require('stream');
+const tmpdir = require('../common/tmpdir');
+
+class Sink extends stream.Writable {
+ constructor() {
+ super();
+ this.chunks = [];
+ }
+
+ _write(chunk, encoding, cb) {
+ this.chunks.push(chunk);
+ cb();
+ }
+}
+
+function direct(config) {
+ const { cipher, key, iv, aad, authTagLength, plaintextLength } = config;
+ const expected = Buffer.alloc(plaintextLength);
+
+ const c = crypto.createCipheriv(cipher, key, iv, { authTagLength });
+ c.setAAD(aad, { plaintextLength });
+ const ciphertext = Buffer.concat([c.update(expected), c.final()]);
+
+ const d = crypto.createDecipheriv(cipher, key, iv, { authTagLength });
+ d.setAAD(aad, { plaintextLength });
+ d.setAuthTag(c.getAuthTag());
+ const actual = Buffer.concat([d.update(ciphertext), d.final()]);
+
+ assert.deepStrictEqual(expected, actual);
+}
+
+function mstream(config) {
+ const { cipher, key, iv, aad, authTagLength, plaintextLength } = config;
+ const expected = Buffer.alloc(plaintextLength);
+
+ const c = crypto.createCipheriv(cipher, key, iv, { authTagLength });
+ c.setAAD(aad, { plaintextLength });
+
+ const plain = new stream.PassThrough();
+ const crypt = new Sink();
+ const chunks = crypt.chunks;
+ plain.pipe(c).pipe(crypt);
+ plain.end(expected);
+
+ crypt.on('close', common.mustCall(() => {
+ const d = crypto.createDecipheriv(cipher, key, iv, { authTagLength });
+ d.setAAD(aad, { plaintextLength });
+ d.setAuthTag(c.getAuthTag());
+
+ const crypt = new stream.PassThrough();
+ const plain = new Sink();
+ crypt.pipe(d).pipe(plain);
+ for (const chunk of chunks) crypt.write(chunk);
+ crypt.end();
+
+ plain.on('close', common.mustCall(() => {
+ const actual = Buffer.concat(plain.chunks);
+ assert.deepStrictEqual(expected, actual);
+ }));
+ }));
+}
+
+function fstream(config) {
+ const count = fstream.count++;
+ const filename = (name) => path.join(tmpdir.path, `${name}${count}`);
+
+ const { cipher, key, iv, aad, authTagLength, plaintextLength } = config;
+ const expected = Buffer.alloc(plaintextLength);
+ fs.writeFileSync(filename('a'), expected);
+
+ const c = crypto.createCipheriv(cipher, key, iv, { authTagLength });
+ c.setAAD(aad, { plaintextLength });
+
+ const plain = fs.createReadStream(filename('a'));
+ const crypt = fs.createWriteStream(filename('b'));
+ plain.pipe(c).pipe(crypt);
+
+ // Observation: 'close' comes before 'end' on |c|, which definitely feels
+ // wrong. Switching to `c.on('end', ...)` doesn't fix the test though.
+ crypt.on('close', common.mustCall(() => {
+ // Just to drive home the point that decryption does actually work:
+ // reading the file synchronously, then decrypting it, works.
+ {
+ const ciphertext = fs.readFileSync(filename('b'));
+ const d = crypto.createDecipheriv(cipher, key, iv, { authTagLength });
+ d.setAAD(aad, { plaintextLength });
+ d.setAuthTag(c.getAuthTag());
+ const actual = Buffer.concat([d.update(ciphertext), d.final()]);
+ assert.deepStrictEqual(expected, actual);
+ }
+
+ const d = crypto.createDecipheriv(cipher, key, iv, { authTagLength });
+ d.setAAD(aad, { plaintextLength });
+ d.setAuthTag(c.getAuthTag());
+
+ const crypt = fs.createReadStream(filename('b'));
+ const plain = fs.createWriteStream(filename('c'));
+ crypt.pipe(d).pipe(plain);
+
+ plain.on('close', common.mustCall(() => {
+ const actual = fs.readFileSync(filename('c'));
+ assert.deepStrictEqual(expected, actual);
+ }));
+ }));
+}
+fstream.count = 0;
+
+function test(config) {
+ direct(config);
+ mstream(config);
+ fstream(config);
+}
+
+tmpdir.refresh();
+
+// OK
+test({
+ cipher: 'aes-128-ccm',
+ aad: Buffer.alloc(1),
+ iv: Buffer.alloc(8),
+ key: Buffer.alloc(16),
+ authTagLength: 16,
+ plaintextLength: 32768,
+});
+
+// Fails the fstream test.
+test({
+ cipher: 'aes-128-ccm',
+ aad: Buffer.alloc(1),
+ iv: Buffer.alloc(8),
+ key: Buffer.alloc(16),
+ authTagLength: 16,
+ plaintextLength: 32769,
+});