Skip to content

Commit def681a

Browse files
stefanmbrvagg
authored andcommitted
crypto: disable crypto.createCipher in FIPS mode
FIPS 140-2 disallows use of MD5, which is used to derive the initialization vector and key for createCipher(). Modify all tests to expect exceptions in FIPS mode when disallowed API is used, or to avoid testing such API in FIPS Mode. PR-URL: #3754 Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Shigeki Ohtsu <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 788541b commit def681a

7 files changed

+116
-88
lines changed

src/node_crypto.cc

+5
Original file line numberDiff line numberDiff line change
@@ -3054,6 +3054,11 @@ void CipherBase::Init(const char* cipher_type,
30543054
int key_buf_len) {
30553055
HandleScope scope(env()->isolate());
30563056

3057+
#ifdef NODE_FIPS_MODE
3058+
return env()->ThrowError(
3059+
"crypto.createCipher() is not supported in FIPS mode.");
3060+
#endif // NODE_FIPS_MODE
3061+
30573062
CHECK_EQ(cipher_, nullptr);
30583063
cipher_ = EVP_get_cipherbyname(cipher_type);
30593064
if (cipher_ == nullptr) {

test/parallel/test-crypto-authenticated.js

+32-20
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,44 @@ for (var i in TEST_CASES) {
9393

9494
(function() {
9595
if (!test.password) return;
96-
var encrypt = crypto.createCipher(test.algo, test.password);
97-
if (test.aad)
98-
encrypt.setAAD(new Buffer(test.aad, 'hex'));
99-
var hex = encrypt.update(test.plain, 'ascii', 'hex');
100-
hex += encrypt.final('hex');
101-
var auth_tag = encrypt.getAuthTag();
102-
// only test basic encryption run if output is marked as tampered.
103-
if (!test.tampered) {
104-
assert.equal(hex.toUpperCase(), test.ct);
105-
assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag);
96+
if (common.hasFipsCrypto) {
97+
assert.throws(function()
98+
{ crypto.createCipher(test.algo, test.password); },
99+
/not supported in FIPS mode/);
100+
} else {
101+
var encrypt = crypto.createCipher(test.algo, test.password);
102+
if (test.aad)
103+
encrypt.setAAD(new Buffer(test.aad, 'hex'));
104+
var hex = encrypt.update(test.plain, 'ascii', 'hex');
105+
hex += encrypt.final('hex');
106+
var auth_tag = encrypt.getAuthTag();
107+
// only test basic encryption run if output is marked as tampered.
108+
if (!test.tampered) {
109+
assert.equal(hex.toUpperCase(), test.ct);
110+
assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag);
111+
}
106112
}
107113
})();
108114

109115
(function() {
110116
if (!test.password) return;
111-
var decrypt = crypto.createDecipher(test.algo, test.password);
112-
decrypt.setAuthTag(new Buffer(test.tag, 'hex'));
113-
if (test.aad)
114-
decrypt.setAAD(new Buffer(test.aad, 'hex'));
115-
var msg = decrypt.update(test.ct, 'hex', 'ascii');
116-
if (!test.tampered) {
117-
msg += decrypt.final('ascii');
118-
assert.equal(msg, test.plain);
117+
if (common.hasFipsCrypto) {
118+
assert.throws(function()
119+
{ crypto.createDecipher(test.algo, test.password); },
120+
/not supported in FIPS mode/);
119121
} else {
120-
// assert that final throws if input data could not be verified!
121-
assert.throws(function() { decrypt.final('ascii'); }, / auth/);
122+
var decrypt = crypto.createDecipher(test.algo, test.password);
123+
decrypt.setAuthTag(new Buffer(test.tag, 'hex'));
124+
if (test.aad)
125+
decrypt.setAAD(new Buffer(test.aad, 'hex'));
126+
var msg = decrypt.update(test.ct, 'hex', 'ascii');
127+
if (!test.tampered) {
128+
msg += decrypt.final('ascii');
129+
assert.equal(msg, test.plain);
130+
} else {
131+
// assert that final throws if input data could not be verified!
132+
assert.throws(function() { decrypt.final('ascii'); }, / auth/);
133+
}
122134
}
123135
})();
124136

test/parallel/test-crypto-binary-default.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,13 @@ function testCipher4(key, iv) {
496496
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
497497
}
498498

499+
if (!common.hasFipsCrypto) {
500+
testCipher1('MySecretKey123');
501+
testCipher1(new Buffer('MySecretKey123'));
499502

500-
testCipher1('MySecretKey123');
501-
testCipher1(new Buffer('MySecretKey123'));
502-
503-
testCipher2('0123456789abcdef');
504-
testCipher2(new Buffer('0123456789abcdef'));
503+
testCipher2('0123456789abcdef');
504+
testCipher2(new Buffer('0123456789abcdef'));
505+
}
505506

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

test/parallel/test-crypto-cipher-decipher.js

+4-59
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ if (!common.hasCrypto) {
66
console.log('1..0 # Skipped: missing crypto');
77
return;
88
}
9+
if (common.hasFipsCrypto) {
10+
console.log('1..0 # Skipped: not supported in FIPS mode');
11+
return;
12+
}
913
var crypto = require('crypto');
1014

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

65-
66-
function testCipher3(key, iv) {
67-
// Test encyrption and decryption with explicit key and iv
68-
var plaintext =
69-
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
70-
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
71-
'jAfaFg**';
72-
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
73-
var ciph = cipher.update(plaintext, 'utf8', 'hex');
74-
ciph += cipher.final('hex');
75-
76-
var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
77-
var txt = decipher.update(ciph, 'hex', 'utf8');
78-
txt += decipher.final('utf8');
79-
80-
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
81-
82-
// streaming cipher interface
83-
// NB: In real life, it's not guaranteed that you can get all of it
84-
// in a single read() like this. But in this case, we know it's
85-
// quite small, so there's no harm.
86-
var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
87-
cStream.end(plaintext);
88-
ciph = cStream.read();
89-
90-
var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
91-
dStream.end(ciph);
92-
txt = dStream.read().toString('utf8');
93-
94-
assert.equal(txt, plaintext, 'streaming cipher iv');
95-
}
96-
97-
98-
function testCipher4(key, iv) {
99-
// Test encyrption and decryption with explicit key and iv
100-
var plaintext =
101-
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
102-
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
103-
'jAfaFg**';
104-
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
105-
var ciph = cipher.update(plaintext, 'utf8', 'buffer');
106-
ciph = Buffer.concat([ciph, cipher.final('buffer')]);
107-
108-
var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
109-
var txt = decipher.update(ciph, 'buffer', 'utf8');
110-
txt += decipher.final('utf8');
111-
112-
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
113-
}
114-
115-
11669
testCipher1('MySecretKey123');
11770
testCipher1(new Buffer('MySecretKey123'));
11871

11972
testCipher2('0123456789abcdef');
12073
testCipher2(new Buffer('0123456789abcdef'));
12174

122-
testCipher3('0123456789abcd0123456789', '12345678');
123-
testCipher3('0123456789abcd0123456789', new Buffer('12345678'));
124-
testCipher3(new Buffer('0123456789abcd0123456789'), '12345678');
125-
testCipher3(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
126-
127-
testCipher4(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
128-
129-
13075
// Base64 padding regression test, see #4837.
13176
(function() {
13277
var c = crypto.createCipher('aes-256-cbc', 'secret');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
var common = require('../common');
3+
var assert = require('assert');
4+
5+
if (!common.hasCrypto) {
6+
console.log('1..0 # Skipped: missing crypto');
7+
return;
8+
}
9+
var crypto = require('crypto');
10+
11+
function testCipher1(key, iv) {
12+
// Test encyrption and decryption with explicit key and iv
13+
var plaintext =
14+
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
15+
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
16+
'jAfaFg**';
17+
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
18+
var ciph = cipher.update(plaintext, 'utf8', 'hex');
19+
ciph += cipher.final('hex');
20+
21+
var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
22+
var txt = decipher.update(ciph, 'hex', 'utf8');
23+
txt += decipher.final('utf8');
24+
25+
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
26+
27+
// streaming cipher interface
28+
// NB: In real life, it's not guaranteed that you can get all of it
29+
// in a single read() like this. But in this case, we know it's
30+
// quite small, so there's no harm.
31+
var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
32+
cStream.end(plaintext);
33+
ciph = cStream.read();
34+
35+
var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
36+
dStream.end(ciph);
37+
txt = dStream.read().toString('utf8');
38+
39+
assert.equal(txt, plaintext, 'streaming cipher iv');
40+
}
41+
42+
43+
function testCipher2(key, iv) {
44+
// Test encyrption and decryption with explicit key and iv
45+
var plaintext =
46+
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
47+
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
48+
'jAfaFg**';
49+
var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
50+
var ciph = cipher.update(plaintext, 'utf8', 'buffer');
51+
ciph = Buffer.concat([ciph, cipher.final('buffer')]);
52+
53+
var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
54+
var txt = decipher.update(ciph, 'buffer', 'utf8');
55+
txt += decipher.final('utf8');
56+
57+
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
58+
}
59+
60+
testCipher1('0123456789abcd0123456789', '12345678');
61+
testCipher1('0123456789abcd0123456789', new Buffer('12345678'));
62+
testCipher1(new Buffer('0123456789abcd0123456789'), '12345678');
63+
testCipher1(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
64+
65+
testCipher2(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));

test/parallel/test-crypto-dh.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ assert.equal(secret1, secret3);
5858

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

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

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

test/parallel/test-crypto.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ assertSorted(crypto.getCurves());
9393
// throw, not assert in C++ land.
9494
assert.throws(function() {
9595
crypto.createCipher('aes192', 'test').update('0', 'hex');
96-
}, /Bad input string/);
96+
}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/);
9797

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

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

0 commit comments

Comments
 (0)