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

crypto: Disable crypto.createCipher in FIPS mode #3754

Closed
wants to merge 1 commit into from
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
5 changes: 5 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3027,6 +3027,11 @@ void CipherBase::Init(const char* cipher_type,
int key_buf_len) {
HandleScope scope(env()->isolate());

#ifdef NODE_FIPS_MODE
return env()->ThrowError(
"crypto.createCipher() is not supported in FIPS mode.");
#endif // NODE_FIPS_MODE

CHECK_EQ(cipher_, nullptr);
cipher_ = EVP_get_cipherbyname(cipher_type);
if (cipher_ == nullptr) {
Expand Down
52 changes: 32 additions & 20 deletions test/parallel/test-crypto-authenticated.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,44 @@ for (var i in TEST_CASES) {

(function() {
if (!test.password) return;
var encrypt = crypto.createCipher(test.algo, test.password);
if (test.aad)
encrypt.setAAD(new Buffer(test.aad, 'hex'));
var hex = encrypt.update(test.plain, 'ascii', 'hex');
hex += encrypt.final('hex');
var auth_tag = encrypt.getAuthTag();
// only test basic encryption run if output is marked as tampered.
if (!test.tampered) {
assert.equal(hex.toUpperCase(), test.ct);
assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag);
if (common.hasFipsCrypto) {
assert.throws(function()
{ crypto.createCipher(test.algo, test.password); },
/not supported in FIPS mode/);
} else {
var encrypt = crypto.createCipher(test.algo, test.password);
if (test.aad)
encrypt.setAAD(new Buffer(test.aad, 'hex'));
var hex = encrypt.update(test.plain, 'ascii', 'hex');
hex += encrypt.final('hex');
var auth_tag = encrypt.getAuthTag();
// only test basic encryption run if output is marked as tampered.
if (!test.tampered) {
assert.equal(hex.toUpperCase(), test.ct);
assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag);
}
}
})();

(function() {
if (!test.password) return;
var decrypt = crypto.createDecipher(test.algo, test.password);
decrypt.setAuthTag(new Buffer(test.tag, 'hex'));
if (test.aad)
decrypt.setAAD(new Buffer(test.aad, 'hex'));
var msg = decrypt.update(test.ct, 'hex', 'ascii');
if (!test.tampered) {
msg += decrypt.final('ascii');
assert.equal(msg, test.plain);
if (common.hasFipsCrypto) {
assert.throws(function()
{ crypto.createDecipher(test.algo, test.password); },
/not supported in FIPS mode/);
} else {
// assert that final throws if input data could not be verified!
assert.throws(function() { decrypt.final('ascii'); }, / auth/);
var decrypt = crypto.createDecipher(test.algo, test.password);
decrypt.setAuthTag(new Buffer(test.tag, 'hex'));
if (test.aad)
decrypt.setAAD(new Buffer(test.aad, 'hex'));
var msg = decrypt.update(test.ct, 'hex', 'ascii');
if (!test.tampered) {
msg += decrypt.final('ascii');
assert.equal(msg, test.plain);
} else {
// assert that final throws if input data could not be verified!
assert.throws(function() { decrypt.final('ascii'); }, / auth/);
}
}
})();

Expand Down
11 changes: 6 additions & 5 deletions test/parallel/test-crypto-binary-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -490,12 +490,13 @@ function testCipher4(key, iv) {
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
}

if (!common.hasFipsCrypto) {
testCipher1('MySecretKey123');
testCipher1(new Buffer('MySecretKey123'));

testCipher1('MySecretKey123');
testCipher1(new Buffer('MySecretKey123'));

testCipher2('0123456789abcdef');
testCipher2(new Buffer('0123456789abcdef'));
testCipher2('0123456789abcdef');
testCipher2(new Buffer('0123456789abcdef'));
}

testCipher3('0123456789abcd0123456789', '12345678');
testCipher3('0123456789abcd0123456789', new Buffer('12345678'));
Expand Down
63 changes: 4 additions & 59 deletions test/parallel/test-crypto-cipher-decipher.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: not supported in FIPS mode');
return;
}
var crypto = require('crypto');

function testCipher1(key) {
Expand Down Expand Up @@ -62,71 +66,12 @@ function testCipher2(key) {
assert.equal(txt, plaintext, 'encryption and decryption with Base64');
}


function testCipher3(key, iv) {
// Test encyrption and decryption with explicit key and iv
var plaintext =
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
'jAfaFg**';
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'hex');
ciph += cipher.final('hex');

var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
var txt = decipher.update(ciph, 'hex', 'utf8');
txt += decipher.final('utf8');

assert.equal(txt, plaintext, 'encryption and decryption with key and iv');

// streaming cipher interface
// NB: In real life, it's not guaranteed that you can get all of it
// in a single read() like this. But in this case, we know it's
// quite small, so there's no harm.
var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
cStream.end(plaintext);
ciph = cStream.read();

var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
dStream.end(ciph);
txt = dStream.read().toString('utf8');

assert.equal(txt, plaintext, 'streaming cipher iv');
}


function testCipher4(key, iv) {
// Test encyrption and decryption with explicit key and iv
var plaintext =
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
'jAfaFg**';
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'buffer');
ciph = Buffer.concat([ciph, cipher.final('buffer')]);

var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
var txt = decipher.update(ciph, 'buffer', 'utf8');
txt += decipher.final('utf8');

assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
}


testCipher1('MySecretKey123');
testCipher1(new Buffer('MySecretKey123'));

testCipher2('0123456789abcdef');
testCipher2(new Buffer('0123456789abcdef'));

testCipher3('0123456789abcd0123456789', '12345678');
testCipher3('0123456789abcd0123456789', new Buffer('12345678'));
testCipher3(new Buffer('0123456789abcd0123456789'), '12345678');
testCipher3(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));

testCipher4(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));


// Base64 padding regression test, see #4837.
(function() {
var c = crypto.createCipher('aes-256-cbc', 'secret');
Expand Down
66 changes: 66 additions & 0 deletions test/parallel/test-crypto-cipheriv-decipheriv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';
var common = require('../common');
var assert = require('assert');

if (!common.hasCrypto) {
console.log('1..0 # Skipped: missing crypto');
return;
}
var crypto = require('crypto');

function testCipher1(key, iv) {
// Test encyrption and decryption with explicit key and iv
var plaintext =
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
'jAfaFg**';
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'hex');
ciph += cipher.final('hex');

var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
var txt = decipher.update(ciph, 'hex', 'utf8');
txt += decipher.final('utf8');

assert.equal(txt, plaintext, 'encryption and decryption with key and iv');

// streaming cipher interface
// NB: In real life, it's not guaranteed that you can get all of it
// in a single read() like this. But in this case, we know it's
// quite small, so there's no harm.
var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
cStream.end(plaintext);
ciph = cStream.read();

var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
dStream.end(ciph);
txt = dStream.read().toString('utf8');

assert.equal(txt, plaintext, 'streaming cipher iv');
}


function testCipher2(key, iv) {
// Test encyrption and decryption with explicit key and iv
var plaintext =
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
'jAfaFg**';
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'buffer');
ciph = Buffer.concat([ciph, cipher.final('buffer')]);

var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
var txt = decipher.update(ciph, 'buffer', 'utf8');
txt += decipher.final('utf8');

assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
}

testCipher1('0123456789abcd0123456789', '12345678');
testCipher1('0123456789abcd0123456789', new Buffer('12345678'));
testCipher1(new Buffer('0123456789abcd0123456789'), '12345678');
testCipher1(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));

testCipher2(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));

4 changes: 2 additions & 2 deletions test/parallel/test-crypto-dh.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ assert.equal(secret1, secret3);

// Run this one twice to make sure that the dh3 clears its error properly
(function() {
var c = crypto.createDecipher('aes-128-ecb', '');
var c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
assert.throws(function() { c.final('utf8'); }, /wrong final block length/);
})();

Expand All @@ -67,7 +67,7 @@ assert.throws(function() {
}, /key is too small/i);

(function() {
var c = crypto.createDecipher('aes-128-ecb', '');
var c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
assert.throws(function() { c.final('utf8'); }, /wrong final block length/);
})();

Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ assertSorted(crypto.getCurves());
// throw, not assert in C++ land.
assert.throws(function() {
crypto.createCipher('aes192', 'test').update('0', 'hex');
}, /Bad input string/);
}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/);

assert.throws(function() {
crypto.createDecipher('aes192', 'test').update('0', 'hex');
}, /Bad input string/);
}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/);

assert.throws(function() {
crypto.createHash('sha1').update('0', 'hex');
Expand Down