From e499ea849c2bb33dd0678ba11c7754366ca2d2cb Mon Sep 17 00:00:00 2001 From: Stefan Budeanu Date: Tue, 10 Nov 2015 14:56:52 -0500 Subject: [PATCH] test: skip/replace weak crypto tests in FIPS mode FIPS 140-2 does not permit the use of MD5 and RC4, skip or tests that use them, or substitute with stronger crypto where applicable. PR-URL: https://github.com/nodejs/node/pull/3757 Reviewed-By: Fedor Indutny Reviewed-By: James Snell Reviewed-By: Shigeki Ohtsu --- test/parallel/test-crypto-binary-default.js | 26 ++++++----- test/parallel/test-crypto-hash.js | 12 +++--- test/parallel/test-crypto-hmac.js | 17 +++++--- test/parallel/test-crypto-stream.js | 28 ++++++------ test/parallel/test-tls-ecdh.js | 2 +- test/parallel/test-tls-getcipher.js | 2 +- test/parallel/test-tls-set-ciphers.js | 2 +- test/pummel/test-crypto-dh.js | 21 +++++---- test/sequential/test-tls-honorcipherorder.js | 45 +++++++++++--------- 9 files changed, 89 insertions(+), 66 deletions(-) diff --git a/test/parallel/test-crypto-binary-default.js b/test/parallel/test-crypto-binary-default.js index 9cc6bdb3e4..6299c86908 100644 --- a/test/parallel/test-crypto-binary-default.js +++ b/test/parallel/test-crypto-binary-default.js @@ -324,11 +324,13 @@ var rfc2202_sha1 = [ ]; for (var i = 0, l = rfc2202_md5.length; i < l; i++) { - assert.equal(rfc2202_md5[i]['hmac'], - crypto.createHmac('md5', rfc2202_md5[i]['key']) - .update(rfc2202_md5[i]['data']) - .digest('hex'), - 'Test HMAC-MD5 : Test case ' + (i + 1) + ' rfc 2202'); + if (!common.hasFipsCrypto) { + assert.equal(rfc2202_md5[i]['hmac'], + crypto.createHmac('md5', rfc2202_md5[i]['key']) + .update(rfc2202_md5[i]['data']) + .digest('hex'), + 'Test HMAC-MD5 : Test case ' + (i + 1) + ' rfc 2202'); + } } for (var i = 0, l = rfc2202_sha1.length; i < l; i++) { assert.equal(rfc2202_sha1[i]['hmac'], @@ -339,15 +341,19 @@ for (var i = 0, l = rfc2202_sha1.length; i < l; i++) { } // Test hashing -var a0 = crypto.createHash('sha1').update('Test123').digest('hex'); -var a1 = crypto.createHash('md5').update('Test123').digest('binary'); +var a1 = crypto.createHash('sha1').update('Test123').digest('hex'); var a2 = crypto.createHash('sha256').update('Test123').digest('base64'); var a3 = crypto.createHash('sha512').update('Test123').digest(); // binary var a4 = crypto.createHash('sha1').update('Test123').digest('buffer'); -assert.equal(a0, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); -assert.equal(a1, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + - '\u00bd\u008c', 'Test MD5 as binary'); +if (!common.hasFipsCrypto) { + var a0 = crypto.createHash('md5').update('Test123').digest('binary'); + assert.equal(a0, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + + '\u00bd\u008c', 'Test MD5 as binary'); +} + +assert.equal(a1, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); + assert.equal(a2, '2bX1jws4GYKTlxhloUB09Z66PoJZW+y+hq5R8dnx9l4=', 'Test SHA256 as base64'); diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index 95bb1bc7d8..90ff1fd727 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -11,8 +11,7 @@ if (!common.hasCrypto) { var crypto = require('crypto'); // Test hashing -var a0 = crypto.createHash('sha1').update('Test123').digest('hex'); -var a1 = crypto.createHash('md5').update('Test123').digest('binary'); +var a1 = crypto.createHash('sha1').update('Test123').digest('hex'); var a2 = crypto.createHash('sha256').update('Test123').digest('base64'); var a3 = crypto.createHash('sha512').update('Test123').digest(); // binary var a4 = crypto.createHash('sha1').update('Test123').digest('buffer'); @@ -38,9 +37,12 @@ a8.write(''); a8.end(); a8 = a8.read(); -assert.equal(a0, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); -assert.equal(a1, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + - '\u00bd\u008c', 'Test MD5 as binary'); +if (!common.hasFipsCrypto) { + var a0 = crypto.createHash('md5').update('Test123').digest('binary'); + assert.equal(a0, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + + '\u00bd\u008c', 'Test MD5 as binary'); +} +assert.equal(a1, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); assert.equal(a2, '2bX1jws4GYKTlxhloUB09Z66PoJZW+y+hq5R8dnx9l4=', 'Test SHA256 as base64'); assert.deepEqual( diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index 692954caab..c244c9e0dd 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -61,6 +61,9 @@ var wikipedia = [ for (var i = 0, l = wikipedia.length; i < l; i++) { for (var hash in wikipedia[i]['hmac']) { + // FIPS does not support MD5. + if (common.hasFipsCrypto && hash == 'md5' ) + continue; var result = crypto.createHmac(hash, wikipedia[i]['key']) .update(wikipedia[i]['data']) .digest('hex'); @@ -346,12 +349,14 @@ var rfc2202_sha1 = [ } ]; -for (var i = 0, l = rfc2202_md5.length; i < l; i++) { - assert.equal(rfc2202_md5[i]['hmac'], - crypto.createHmac('md5', rfc2202_md5[i]['key']) - .update(rfc2202_md5[i]['data']) - .digest('hex'), - 'Test HMAC-MD5 : Test case ' + (i + 1) + ' rfc 2202'); +if (!common.hasFipsCrypto) { + for (var i = 0, l = rfc2202_md5.length; i < l; i++) { + assert.equal(rfc2202_md5[i]['hmac'], + crypto.createHmac('md5', rfc2202_md5[i]['key']) + .update(rfc2202_md5[i]['data']) + .digest('hex'), + 'Test HMAC-MD5 : Test case ' + (i + 1) + ' rfc 2202'); + } } for (var i = 0, l = rfc2202_sha1.length; i < l; i++) { assert.equal(rfc2202_sha1[i]['hmac'], diff --git a/test/parallel/test-crypto-stream.js b/test/parallel/test-crypto-stream.js index 727e6a16a7..f276e16172 100644 --- a/test/parallel/test-crypto-stream.js +++ b/test/parallel/test-crypto-stream.js @@ -26,19 +26,21 @@ Stream2buffer.prototype._write = function(data, encodeing, done) { return done(null); }; -// Create an md5 hash of "Hallo world" -var hasher1 = crypto.createHash('md5'); -hasher1.pipe(new Stream2buffer(common.mustCall(function end(err, hash) { - assert.equal(err, null); - assert.equal(hash.toString('hex'), '06460dadb35d3d503047ce750ceb2d07'); -}))); -hasher1.end('Hallo world'); - -// Simpler check for unpipe, setEncoding, pause and resume -crypto.createHash('md5').unpipe({}); -crypto.createHash('md5').setEncoding('utf8'); -crypto.createHash('md5').pause(); -crypto.createHash('md5').resume(); +if (!common.hasFipsCrypto) { + // Create an md5 hash of "Hallo world" + var hasher1 = crypto.createHash('md5'); + hasher1.pipe(new Stream2buffer(common.mustCall(function end(err, hash) { + assert.equal(err, null); + assert.equal(hash.toString('hex'), '06460dadb35d3d503047ce750ceb2d07'); + }))); + hasher1.end('Hallo world'); + + // Simpler check for unpipe, setEncoding, pause and resume + crypto.createHash('md5').unpipe({}); + crypto.createHash('md5').setEncoding('utf8'); + crypto.createHash('md5').pause(); + crypto.createHash('md5').resume(); +} // Decipher._flush() should emit an error event, not an exception. var key = new Buffer('48fb56eb10ffeb13fc0ef551bbca3b1b', 'hex'), diff --git a/test/parallel/test-tls-ecdh.js b/test/parallel/test-tls-ecdh.js index ce9af395c5..a6e16114b9 100644 --- a/test/parallel/test-tls-ecdh.js +++ b/test/parallel/test-tls-ecdh.js @@ -14,7 +14,7 @@ var fs = require('fs'); var options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'), - ciphers: '-ALL:ECDHE-RSA-RC4-SHA', + ciphers: '-ALL:ECDHE-RSA-AES128-SHA256', ecdhCurve: 'prime256v1' }; diff --git a/test/parallel/test-tls-getcipher.js b/test/parallel/test-tls-getcipher.js index 62209c771c..646d396eca 100644 --- a/test/parallel/test-tls-getcipher.js +++ b/test/parallel/test-tls-getcipher.js @@ -9,7 +9,7 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var cipher_list = ['RC4-SHA', 'AES256-SHA']; +var cipher_list = ['AES128-SHA256', 'AES256-SHA256']; var cipher_version_pattern = /TLS|SSL/; var options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), diff --git a/test/parallel/test-tls-set-ciphers.js b/test/parallel/test-tls-set-ciphers.js index a303f6fb27..696644cdc4 100644 --- a/test/parallel/test-tls-set-ciphers.js +++ b/test/parallel/test-tls-set-ciphers.js @@ -19,7 +19,7 @@ var fs = require('fs'); var options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'), - ciphers: 'RC4-MD5' + ciphers: 'DES-CBC3-SHA' }; var reply = 'I AM THE WALRUS'; // something recognizable diff --git a/test/pummel/test-crypto-dh.js b/test/pummel/test-crypto-dh.js index a223e45c86..1a2020cd55 100644 --- a/test/pummel/test-crypto-dh.js +++ b/test/pummel/test-crypto-dh.js @@ -20,27 +20,30 @@ assert.throws(function() { }); var hashes = { - modp1 : 'b4b330a6ffeacfbd861e7fe2135b4431', - modp2 : '7c3c5cad8b9f378d88f1dd64a4b6413a', - modp5 : 'b1d2acc22c542e08669a5c5ae812694d', - modp14 : '8d041538cecc1a7d915ba4b718f8ad20', - modp15 : 'dc3b93def24e078c4fbf92d5e14ba69b', - modp16 : 'a273487f46f699461f613b3878d9dfd9', - modp17 : 'dc76e09935310348c492de9bd82014d0', - modp18 : 'db08973bfd2371758a69db180871c993' + modp1 : '630e9acd2cc63f7e80d8507624ba60ac0757201a', + modp2 : '18f7aa964484137f57bca64b21917a385b6a0b60', + modp5 : 'c0a8eec0c2c8a5ec2f9c26f9661eb339a010ec61', + modp14 : 'af5455606fe74cec49782bb374e4c63c9b1d132c', + modp15 : '7bdd39e5cdbb9748113933e5c2623b559c534e74', + modp16 : 'daea5277a7ad0116e734a8e0d2f297ef759d1161', + modp17 : '3b62aaf0142c2720f0bf26a9589b0432c00eadc1', + modp18 : 'a870b491bbbec9b131ae9878d07449d32e54f160' }; for (var name in hashes) { var group = crypto.getDiffieHellman(name); var private_key = group.getPrime('hex'); var hash1 = hashes[name]; - var hash2 = crypto.createHash('md5') + var hash2 = crypto.createHash('sha1') .update(private_key.toUpperCase()).digest('hex'); assert.equal(hash1, hash2); assert.equal(group.getGenerator('hex'), '02'); } for (var name in hashes) { + // modp1 is 768 bits, FIPS requires >= 1024 + if (name == 'modp1' && common.hasFipsCrypto) + continue; var group1 = crypto.getDiffieHellman(name); var group2 = crypto.getDiffieHellman(name); group1.generateKeys(); diff --git a/test/sequential/test-tls-honorcipherorder.js b/test/sequential/test-tls-honorcipherorder.js index cac697c5b0..28c930b07e 100644 --- a/test/sequential/test-tls-honorcipherorder.js +++ b/test/sequential/test-tls-honorcipherorder.js @@ -10,9 +10,10 @@ var tls = require('tls'); var fs = require('fs'); var nconns = 0; -// test only in TLSv1 to use DES which is no longer supported TLSv1.2 -// to be safe when the default method is updated in the future -var SSL_Method = 'TLSv1_method'; + +// We explicitly set TLS version to 1.2 so as to be safe when the +// default method is updated in the future +var SSL_Method = 'TLSv1_2_method'; var localhost = '127.0.0.1'; process.on('exit', function() { @@ -24,7 +25,8 @@ function test(honorCipherOrder, clientCipher, expectedCipher, cb) { secureProtocol: SSL_Method, key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'), - ciphers: 'DES-CBC-SHA:AES256-SHA:RC4-SHA:ECDHE-RSA-AES256-SHA', + ciphers: 'AES256-SHA256:AES128-GCM-SHA256:AES128-SHA256:' + + 'ECDHE-RSA-AES128-GCM-SHA256', honorCipherOrder: !!honorCipherOrder }; @@ -57,37 +59,40 @@ test1(); function test1() { // Client has the preference of cipher suites by default - test(false, 'AES256-SHA:DES-CBC-SHA:RC4-SHA', 'AES256-SHA', test2); + test(false, 'AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256', + 'AES128-GCM-SHA256', test2); } function test2() { - // Server has the preference of cipher suites where DES-CBC-SHA is in - // the first. - test(true, 'AES256-SHA:DES-CBC-SHA:RC4-SHA', 'DES-CBC-SHA', test3); + // Server has the preference of cipher suites, and AES256-SHA256 is + // the server's top choice. + test(true, 'AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256', + 'AES256-SHA256', test3); } function test3() { - // Server has the preference of cipher suites. RC4-SHA is given - // higher priority over DES-CBC-SHA among client cipher suites. - test(true, 'RC4-SHA:AES256-SHA', 'AES256-SHA', test4); + // Server has the preference of cipher suites. AES128-GCM-SHA256 is given + // higher priority over AES128-SHA256 among client cipher suites. + test(true, 'AES128-SHA256:AES128-GCM-SHA256', 'AES128-GCM-SHA256', test4); + } function test4() { - // As client has only one cipher, server has no choice in regardless + // As client has only one cipher, server has no choice, irrespective // of honorCipherOrder. - test(true, 'RC4-SHA', 'RC4-SHA', test5); + test(true, 'AES128-SHA256', 'AES128-SHA256', test5); } function test5() { - // Client did not explicitly set ciphers. Ensure that client defaults to - // sane ciphers. Even though server gives top priority to DES-CBC-SHA - // it should not be negotiated because it's not in default client ciphers. - test(true, null, 'AES256-SHA', test6); + // Client did not explicitly set ciphers and client offers + // tls.DEFAULT_CIPHERS. All ciphers of the server are included in the + // default list so the negotiated cipher is selected according to the + // server's top preference of AES256-SHA256. + test(true, null, 'AES256-SHA256', test6); } function test6() { // Ensure that `tls.DEFAULT_CIPHERS` is used - SSL_Method = 'TLSv1_2_method'; - tls.DEFAULT_CIPHERS = 'ECDHE-RSA-AES256-SHA'; - test(true, null, 'ECDHE-RSA-AES256-SHA'); + tls.DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-GCM-SHA256'; + test(true, null, 'ECDHE-RSA-AES128-GCM-SHA256'); }