From 5bdb18e09133fe2f88b0e412e15480d41e974dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sat, 9 Dec 2017 13:23:18 +0100 Subject: [PATCH] crypto: warn on invalid authentication tag length Backport-PR-URL: https://github.com/nodejs/node/pull/18347 PR-URL: https://github.com/nodejs/node/pull/17566 Refs: https://github.com/nodejs/node/issues/17523 Reviewed-By: Ben Noordhuis Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- src/node_crypto.cc | 10 +++++++++- test/parallel/test-crypto-authenticated.js | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) 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))); + } +}