test: skip/replace weak crypto tests in FIPS mode
authorStefan Budeanu <stefan@budeanu.com>
Tue, 10 Nov 2015 19:56:52 +0000 (14:56 -0500)
committerJames M Snell <jasnell@gmail.com>
Wed, 23 Dec 2015 16:38:33 +0000 (08:38 -0800)
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 <fedor@indutny.com>
Reviewed-By: James Snell <jasnell@gmail.com>
Reviewed-By: Shigeki Ohtsu <ohtsu@iij.ad.jp>
test/parallel/test-crypto-binary-default.js
test/parallel/test-crypto-hash.js
test/parallel/test-crypto-hmac.js
test/parallel/test-crypto-stream.js
test/parallel/test-tls-ecdh.js
test/parallel/test-tls-getcipher.js
test/parallel/test-tls-set-ciphers.js
test/pummel/test-crypto-dh.js
test/sequential/test-tls-honorcipherorder.js

index 8695632..ad064ba 100644 (file)
@@ -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');
 
index 95bb1bc..90ff1fd 100644 (file)
@@ -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(
index 692954c..c244c9e 100644 (file)
@@ -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'],
index 727e6a1..f276e16 100644 (file)
@@ -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'),
index ce9af39..a6e1611 100644 (file)
@@ -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'
 };
 
index 62209c7..646d396 100644 (file)
@@ -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'),
index a303f6f..696644c 100644 (file)
@@ -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
index a223e45..1a2020c 100644 (file)
@@ -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();
index cac697c..28c930b 100644 (file)
@@ -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');
 }