Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: increase crypto strength for FIPS standard #3758

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/parallel/test-crypto-binary-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ assert.throws(function() {

// Test Diffie-Hellman with two parties sharing a secret,
// using various encodings as we go along
var dh1 = crypto.createDiffieHellman(256);
var dh1 = crypto.createDiffieHellman(1024);
var p1 = dh1.getPrime('buffer');
var dh2 = crypto.createDiffieHellman(p1, 'base64');
var key1 = dh1.generateKeys();
Expand Down
19 changes: 14 additions & 5 deletions test/parallel/test-crypto-dh-odd-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ if (!common.hasCrypto) {
}
var crypto = require('crypto');

var odd = new Buffer(39);
odd.fill('A');
function test() {
var odd = new Buffer(39);
odd.fill('A');

var c = crypto.createDiffieHellman(32);
c.setPrivateKey(odd);
c.generateKeys();
var c = crypto.createDiffieHellman(32);
c.setPrivateKey(odd);
c.generateKeys();
}

// FIPS requires a length of at least 1024
if (!common.hasFipsCrypto) {
assert.doesNotThrow(function() { test(); });
} else {
assert.throws(function() { test(); }, /key size too small/);
}
69 changes: 37 additions & 32 deletions test/parallel/test-crypto-dh.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var crypto = require('crypto');

// Test Diffie-Hellman with two parties sharing a secret,
// using various encodings as we go along
var dh1 = crypto.createDiffieHellman(256);
var dh1 = crypto.createDiffieHellman(1024);
var p1 = dh1.getPrime('buffer');
var dh2 = crypto.createDiffieHellman(p1, 'buffer');
var key1 = dh1.generateKeys();
Expand Down Expand Up @@ -82,9 +82,11 @@ assert.equal(aSecret, bSecret);
assert.equal(alice.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(bob.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);

// Ensure specific generator (buffer) works as expected.
var modp1 = crypto.createDiffieHellmanGroup('modp1');
var modp1buf = new Buffer([
/* Ensure specific generator (buffer) works as expected.
* The values below (modp2/modp2buf) are for a 1024 bits long prime from
* RFC 2412 E.2, see https://tools.ietf.org/html/rfc2412. */
var modp2 = crypto.createDiffieHellmanGroup('modp2');
var modp2buf = new Buffer([
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f,
0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b,
0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67,
Expand All @@ -93,47 +95,50 @@ var modp1buf = new Buffer([
0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51,
0xc2, 0x45, 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff,
0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed, 0xee, 0x38, 0x6b, 0xfb,
0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b,
0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe6, 0x53, 0x81,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
]);
var exmodp1 = crypto.createDiffieHellman(modp1buf, new Buffer([2]));
modp1.generateKeys();
exmodp1.generateKeys();
var modp1Secret = modp1.computeSecret(exmodp1.getPublicKey()).toString('hex');
var exmodp1Secret = exmodp1.computeSecret(modp1.getPublicKey()).toString('hex');
assert.equal(modp1Secret, exmodp1Secret);
assert.equal(modp1.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(exmodp1.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
var exmodp2 = crypto.createDiffieHellman(modp2buf, new Buffer([2]));
modp2.generateKeys();
exmodp2.generateKeys();
var modp2Secret = modp2.computeSecret(exmodp2.getPublicKey()).toString('hex');
var exmodp2Secret = exmodp2.computeSecret(modp2.getPublicKey()).toString('hex');
assert.equal(modp2Secret, exmodp2Secret);
assert.equal(modp2.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(exmodp2.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);


// Ensure specific generator (string with encoding) works as expected.
var exmodp1_2 = crypto.createDiffieHellman(modp1buf, '02', 'hex');
exmodp1_2.generateKeys();
modp1Secret = modp1.computeSecret(exmodp1_2.getPublicKey()).toString('hex');
var exmodp1_2Secret = exmodp1_2.computeSecret(modp1.getPublicKey())
var exmodp2_2 = crypto.createDiffieHellman(modp2buf, '02', 'hex');
exmodp2_2.generateKeys();
modp2Secret = modp2.computeSecret(exmodp2_2.getPublicKey()).toString('hex');
var exmodp2_2Secret = exmodp2_2.computeSecret(modp2.getPublicKey())
.toString('hex');
assert.equal(modp1Secret, exmodp1_2Secret);
assert.equal(exmodp1_2.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(modp2Secret, exmodp2_2Secret);
assert.equal(exmodp2_2.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);


// Ensure specific generator (string without encoding) works as expected.
var exmodp1_3 = crypto.createDiffieHellman(modp1buf, '\x02');
exmodp1_3.generateKeys();
modp1Secret = modp1.computeSecret(exmodp1_3.getPublicKey()).toString('hex');
var exmodp1_3Secret = exmodp1_3.computeSecret(modp1.getPublicKey())
var exmodp2_3 = crypto.createDiffieHellman(modp2buf, '\x02');
exmodp2_3.generateKeys();
modp2Secret = modp2.computeSecret(exmodp2_3.getPublicKey()).toString('hex');
var exmodp2_3Secret = exmodp2_3.computeSecret(modp2.getPublicKey())
.toString('hex');
assert.equal(modp1Secret, exmodp1_3Secret);
assert.equal(exmodp1_3.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(modp2Secret, exmodp2_3Secret);
assert.equal(exmodp2_3.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);


// Ensure specific generator (numeric) works as expected.
var exmodp1_4 = crypto.createDiffieHellman(modp1buf, 2);
exmodp1_4.generateKeys();
modp1Secret = modp1.computeSecret(exmodp1_4.getPublicKey()).toString('hex');
var exmodp1_4Secret = exmodp1_4.computeSecret(modp1.getPublicKey())
var exmodp2_4 = crypto.createDiffieHellman(modp2buf, 2);
exmodp2_4.generateKeys();
modp2Secret = modp2.computeSecret(exmodp2_4.getPublicKey()).toString('hex');
var exmodp2_4Secret = exmodp2_4.computeSecret(modp2.getPublicKey())
.toString('hex');
assert.equal(modp1Secret, exmodp1_4Secret);
assert.equal(exmodp1_4.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
assert.equal(modp2Secret, exmodp2_4Secret);
assert.equal(exmodp2_4.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);


var p = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' +
Expand Down
4 changes: 4 additions & 0 deletions test/parallel/test-crypto-ecb.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ if (!common.hasCrypto) {
console.log('1..0 # Skipped: missing crypto');
return;
}
if (common.hasFipsCrypto) {
console.log('1..0 # Skipped: BF-ECB is not FIPS 140-2 compatible');
return;
}
var crypto = require('crypto');

crypto.DEFAULT_ENCODING = 'buffer';
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ assert.throws(function() {
''
].join('\n');
crypto.createSign('RSA-SHA256').update('test').sign(priv);
}, /RSA_sign:digest too big for rsa key/);
}, /digest too big for rsa key/);

assert.throws(function() {
// The correct header inside `test_bad_rsa_privkey.pem` should have been
Expand Down
81 changes: 73 additions & 8 deletions test/parallel/test-dh-padding.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,83 @@ try {
return;
}

var prime = 'c51f7bf8f0e1cf899243cdf408b1bc7c09c010e33ef7f3fbe5bd5feaf906113b';
var apub = '6fe9f37037d8d017f908378c1ee04fe60e1cd3668bfc5075fac55c2f7153dd84';
var bpub = '31d83e167fdf956c9dae6b980140577a9f8868acbfcbdc19113e58bfb9223abc';
var apriv = '4fbfd4661f9181bbf574537b1a78adf473e8e771eef13c605e963c0f3094b697';
var secret = '25616eed33f1af7975bbd0a8071d98a014f538b243bef90d76c08e81a0b3c500';
/* This test verifies padding with leading zeroes for shared
* secrets that are strictly smaller than the modulus (prime).
* See:
* RFC 4346: https://www.ietf.org/rfc/rfc4346.txt
* https://github.com/nodejs/node-v0.x-archive/issues/7906
* https://github.com/nodejs/node-v0.x-archive/issues/5239
*
* In FIPS mode OPENSSL_DH_FIPS_MIN_MODULUS_BITS = 1024, meaning we need
* a FIPS-friendly >= 1024 bit prime, we can use MODP 14 from RFC 3526:
* https://www.ietf.org/rfc/rfc3526.txt
*
* We can generate appropriate values with this code:
*
* crypto = require('crypto');
*
* for (;;) {
* var a = crypto.getDiffieHellman('modp14'),
* var b = crypto.getDiffieHellman('modp14');
*
* a.generateKeys();
* b.generateKeys();
*
* var aSecret = a.computeSecret(b.getPublicKey()).toString('hex');
* console.log("A public: " + a.getPublicKey().toString('hex'));
* console.log("A private: " + a.getPrivateKey().toString('hex'));
* console.log("B public: " + b.getPublicKey().toString('hex'));
* console.log("B private: " + b.getPrivateKey().toString('hex'));
* console.log("A secret: " + aSecret);
* console.log('-------------------------------------------------');
* if(aSecret.substring(0,2) === "00") {
* console.log("found short key!");
* return;
* }
* }
*/

var p = crypto.createDiffieHellman(prime, 'hex');
var apub =
'5484455905d3eff34c70980e871f27f05448e66f5a6efbb97cbcba4e927196c2bd9ea272cded91\
10a4977afa8d9b16c9139a444ed2d954a794650e5d7cb525204f385e1af81530518563822ecd0f9\
524a958d02b3c269e79d6d69850f0968ad567a4404fbb0b19efc8bc73e267b6136b88cafb33299f\
f7c7cace3ffab1a88c2c9ee841f88b4c3679b4efc465f5c93cca11d487be57373e4c5926f634c4e\
efee6721d01db91cd66321615b2522f96368dbc818875d422140d0edf30bdb97d9721feddcb9ff6\
453741a4f687ee46fc54bf1198801f1210ac789879a5ee123f79e2d2ce1209df2445d32166bc9e4\
8f89e944ec9c3b2e16c8066cd8eebd4e33eb941';
var bpub =
'3fca64510e36bc7da8a3a901c7b74c2eabfa25deaf7cbe1d0c50235866136ad677317279e1fb0\
06e9c0a07f63e14a3363c8e016fbbde2b2c7e79fed1cc3e08e95f7459f547a8cd0523ee9dc744d\
e5a956d92b937db4448917e1f6829437f05e408ee7aea70c0362b37370c7c75d14449d8b2d2133\
04ac972302d349975e2265ca7103cfebd019d9e91234d638611abd049014f7abf706c1c5da6c88\
788a1fdc6cdf17f5fffaf024ce8711a2ebde0b52e9f1cb56224483826d6e5ac6ecfaae07b75d20\
6e8ac97f5be1a5b68f20382f2a7dac189cf169325c4cf845b26a0cd616c31fec905c5d9035e5f7\
8e9880c812374ac0f3ca3d365f06e4be526b5affd4b79';
var apriv =
'62411e34704637d99c6c958a7db32ac22fcafafbe1c33d2cfdb76e12ded41f38fc16b792b9041\
2e4c82755a3815ba52f780f0ee296ad46e348fc4d1dcd6b64f4eea1b231b2b7d95c5b1c2e26d34\
83520558b9860a6eb668f01422a54e6604aa7702b4e67511397ef3ecb912bff1a83899c5a5bfb2\
0ee29249a91b8a698e62486f7009a0e9eaebda69d77ecfa2ca6ba2db6c8aa81759c8c90c675979\
08c3b3e6fc60668f7be81cce6784482af228dd7f489005253a165e292802cfd0399924f6c56827\
7012f68255207722355634290acc7fddeefbba75650a85ece95b6a12de67eac016ba78960108dd\
5dbadfaa43cc9fed515a1f307b7d90ae0623bc7b8cefb';
var secret =
'00c37b1e06a436d6717816a40e6d72907a6f255638b93032267dcb9a5f0b4a9aa0236f3dce63b\
1c418c60978a00acd1617dfeecf1661d8a3fafb4d0d8824386750f4853313400e7e4afd22847e4\
fa56bc9713872021265111906673b38db83d10cbfa1dea3b6b4c97c8655f4ae82125281af7f234\
8916a15c6f95649367d169d587697480df4d10b381479e86d5518b520d9d8fb764084eab518224\
dc8fe984ddaf532fc1531ce43155fa0ab32532bf1ece5356b8a3447b5267798a904f16f3f4e635\
597adc0179d011132dcffc0bbcb0dd2c8700872f8663ec7ddd897c659cc2efebccc73f38f0ec96\
8612314311231f905f91c63a1aea52e0b60cead8b57df';

/* FIPS-friendly 2048 bit prime */
var p = crypto.createDiffieHellman(
crypto.getDiffieHellman('modp14').getPrime());

p.setPublicKey(apub, 'hex');
p.setPrivateKey(apriv, 'hex');

assert.equal(
p.computeSecret(bpub, 'hex', 'hex'),
'0025616eed33f1af7975bbd0a8071d98a014f538b243bef90d76c08e81a0b3c5'
p.computeSecret(bpub, 'hex', 'hex').toString('hex'),
secret
);
2 changes: 1 addition & 1 deletion test/pummel/test-dh-regr.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (!common.hasCrypto) {
}
var crypto = require('crypto');

var p = crypto.createDiffieHellman(256).getPrime();
var p = crypto.createDiffieHellman(1024).getPrime();

for (var i = 0; i < 2000; i++) {
var a = crypto.createDiffieHellman(p),
Expand Down