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

File tree

7 files changed

+116
-88
lines changed

7 files changed

+116
-88
lines changed

‎src/node_crypto.cc‎

Lines changed: 5 additions & 0 deletions
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+
returnenv()->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‎

Lines changed: 32 additions & 20 deletions
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-
varencrypt=crypto.createCipher(test.algo,test.password);
97-
if(test.aad)
98-
encrypt.setAAD(newBuffer(test.aad,'hex'));
99-
varhex=encrypt.update(test.plain,'ascii','hex');
100-
hex+=encrypt.final('hex');
101-
varauth_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+
/notsupportedinFIPSmode/);
100+
}else{
101+
varencrypt=crypto.createCipher(test.algo,test.password);
102+
if(test.aad)
103+
encrypt.setAAD(newBuffer(test.aad,'hex'));
104+
varhex=encrypt.update(test.plain,'ascii','hex');
105+
hex+=encrypt.final('hex');
106+
varauth_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-
vardecrypt=crypto.createDecipher(test.algo,test.password);
112-
decrypt.setAuthTag(newBuffer(test.tag,'hex'));
113-
if(test.aad)
114-
decrypt.setAAD(newBuffer(test.aad,'hex'));
115-
varmsg=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+
/notsupportedinFIPSmode/);
119121
}else{
120-
// assert that final throws if input data could not be verified!
121-
assert.throws(function(){decrypt.final('ascii');},/auth/);
122+
vardecrypt=crypto.createDecipher(test.algo,test.password);
123+
decrypt.setAuthTag(newBuffer(test.tag,'hex'));
124+
if(test.aad)
125+
decrypt.setAAD(newBuffer(test.aad,'hex'));
126+
varmsg=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‎

Lines changed: 6 additions & 5 deletions
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(newBuffer('MySecretKey123'));
499502

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

506507
testCipher3('0123456789abcd0123456789','12345678');
507508
testCipher3('0123456789abcd0123456789',newBuffer('12345678'));

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

Lines changed: 4 additions & 59 deletions
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
varcrypto=require('crypto');
1014

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

65-
66-
functiontestCipher3(key,iv){
67-
// Test encyrption and decryption with explicit key and iv
68-
varplaintext=
69-
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw'+
70-
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ'+
71-
'jAfaFg**';
72-
varcipher=crypto.createCipheriv('des-ede3-cbc',key,iv);
73-
varciph=cipher.update(plaintext,'utf8','hex');
74-
ciph+=cipher.final('hex');
75-
76-
vardecipher=crypto.createDecipheriv('des-ede3-cbc',key,iv);
77-
vartxt=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-
varcStream=crypto.createCipheriv('des-ede3-cbc',key,iv);
87-
cStream.end(plaintext);
88-
ciph=cStream.read();
89-
90-
vardStream=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-
functiontestCipher4(key,iv){
99-
// Test encyrption and decryption with explicit key and iv
100-
varplaintext=
101-
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw'+
102-
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ'+
103-
'jAfaFg**';
104-
varcipher=crypto.createCipheriv('des-ede3-cbc',key,iv);
105-
varciph=cipher.update(plaintext,'utf8','buffer');
106-
ciph=Buffer.concat([ciph,cipher.final('buffer')]);
107-
108-
vardecipher=crypto.createDecipheriv('des-ede3-cbc',key,iv);
109-
vartxt=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(newBuffer('MySecretKey123'));
11871

11972
testCipher2('0123456789abcdef');
12073
testCipher2(newBuffer('0123456789abcdef'));
12174

122-
testCipher3('0123456789abcd0123456789','12345678');
123-
testCipher3('0123456789abcd0123456789',newBuffer('12345678'));
124-
testCipher3(newBuffer('0123456789abcd0123456789'),'12345678');
125-
testCipher3(newBuffer('0123456789abcd0123456789'),newBuffer('12345678'));
126-
127-
testCipher4(newBuffer('0123456789abcd0123456789'),newBuffer('12345678'));
128-
129-
13075
// Base64 padding regression test, see #4837.
13176
(function(){
13277
varc=crypto.createCipher('aes-256-cbc','secret');
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
varcommon=require('../common');
3+
varassert=require('assert');
4+
5+
if(!common.hasCrypto){
6+
console.log('1..0 # Skipped: missing crypto');
7+
return;
8+
}
9+
varcrypto=require('crypto');
10+
11+
functiontestCipher1(key,iv){
12+
// Test encyrption and decryption with explicit key and iv
13+
varplaintext=
14+
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw'+
15+
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ'+
16+
'jAfaFg**';
17+
varcipher=crypto.createCipheriv('des-ede3-cbc',key,iv);
18+
varciph=cipher.update(plaintext,'utf8','hex');
19+
ciph+=cipher.final('hex');
20+
21+
vardecipher=crypto.createDecipheriv('des-ede3-cbc',key,iv);
22+
vartxt=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+
varcStream=crypto.createCipheriv('des-ede3-cbc',key,iv);
32+
cStream.end(plaintext);
33+
ciph=cStream.read();
34+
35+
vardStream=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+
functiontestCipher2(key,iv){
44+
// Test encyrption and decryption with explicit key and iv
45+
varplaintext=
46+
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw'+
47+
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ'+
48+
'jAfaFg**';
49+
varcipher=crypto.createCipheriv('des-ede3-cbc',key,iv);
50+
varciph=cipher.update(plaintext,'utf8','buffer');
51+
ciph=Buffer.concat([ciph,cipher.final('buffer')]);
52+
53+
vardecipher=crypto.createDecipheriv('des-ede3-cbc',key,iv);
54+
vartxt=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',newBuffer('12345678'));
62+
testCipher1(newBuffer('0123456789abcd0123456789'),'12345678');
63+
testCipher1(newBuffer('0123456789abcd0123456789'),newBuffer('12345678'));
64+
65+
testCipher2(newBuffer('0123456789abcd0123456789'),newBuffer('12345678'));

‎test/parallel/test-crypto-dh.js‎

Lines changed: 2 additions & 2 deletions
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-
varc=crypto.createDecipher('aes-128-ecb','');
61+
varc=crypto.createDecipheriv('aes-128-ecb',crypto.randomBytes(16),'');
6262
assert.throws(function(){c.final('utf8');},/wrongfinalblocklength/);
6363
})();
6464

@@ -67,7 +67,7 @@ assert.throws(function(){
6767
},/keyistoosmall/i);
6868

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

‎test/parallel/test-crypto.js‎

Lines changed: 2 additions & 2 deletions
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-
},/Badinputstring/);
96+
},common.hasFipsCrypto ? /notsupportedinFIPSmode/ : /Badinputstring/);
9797

9898
assert.throws(function(){
9999
crypto.createDecipher('aes192','test').update('0','hex');
100-
},/Badinputstring/);
100+
},common.hasFipsCrypto ? /notsupportedinFIPSmode/ : /Badinputstring/);
101101

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

0 commit comments

Comments
(0)