diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 70b5602a4eda13..a439063c47bc10 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -3525,8 +3525,16 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo& args) { CipherBase* cipher; ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); + // Restrict GCM tag lengths according to NIST 800-38d, page 9. + unsigned int tag_len = Buffer::Length(buf); + if (tag_len > 16 || (tag_len < 12 && tag_len != 8 && tag_len != 4)) { + ProcessEmitWarning(cipher->env(), + "Permitting authentication tag lengths of %u bytes is deprecated. " + "Valid GCM tag lengths are 4, 8, 12, 13, 14, 15, 16.", + tag_len); + } - if (!cipher->SetAuthTag(Buffer::Data(buf), Buffer::Length(buf))) + if (!cipher->SetAuthTag(Buffer::Data(buf), tag_len)) env->ThrowError("Attempting to set auth tag in unsupported state"); } diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index b94ddb2e5782b8..b6a519186844de 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -314,6 +314,14 @@ const errMessages = { const ciphers = crypto.getCiphers(); +common.expectWarning('Warning', (common.hasFipsCrypto ? [] : [ + 'Use Cipheriv for counter mode of aes-192-gcm' +]).concat( + [0, 1, 2, 6, 9, 10, 11, 17] + .map((i) => `Permitting authentication tag lengths of ${i} bytes is ` + + 'deprecated. Valid GCM tag lengths are 4, 8, 12, 13, 14, 15, 16.') +)); + for (const i in TEST_CASES) { const test = TEST_CASES[i]; @@ -455,3 +463,14 @@ for (const i in TEST_CASES) { assert.throws(() => encrypt.setAAD(Buffer.from('123', 'ascii')), errMessages.state); } + +// GCM only supports specific authentication tag lengths, invalid lengths should +// produce warnings. +{ + for (const length of [0, 1, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]) { + const decrypt = crypto.createDecipheriv('aes-256-gcm', + 'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8', + 'qkuZpJWCewa6Szih'); + decrypt.setAuthTag(Buffer.from('1'.repeat(length))); + } +} diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index ad7fc54ea90003..14a1601981f353 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -141,7 +141,7 @@ testCipher2(Buffer.from('0123456789abcdef')); // setAutoPadding/setAuthTag/setAAD should return `this` { const key = '0123456789'; - const tagbuf = Buffer.from('tagbuf'); + const tagbuf = Buffer.from('auth_tag'); const aadbuf = Buffer.from('aadbuf'); const decipher = crypto.createDecipher('aes-256-gcm', key); assert.strictEqual(decipher.setAutoPadding(), decipher);