Skip to content

Commit 2e7270b

Browse files
shigekiMylesBorins
authored andcommitted
crypto: fix error of createCipher in wrap mode
EVP_CIPHER_CTX_FLAG_WRAP_ALLOW flag needs to be set in using wrap mode ciphers. In `crypto.createCipher()`, AES key wrap mode does not use a default IV defined in RFC3394 but a generated IV with `EVP_BytesToKey()` to be consistent API behaviors with other ciphers. The built-in AES wrap mode in OpenSSL is not supported in FIPS mode as http://openssl.6102.n7.nabble.com/AES-Key-Wrap-in-FIPS-Mode-td50238.html so its tests in FIPS mode are skipped. Backport-PR-URL: #16584 Fixes: #15009 PR-URL: #15037 Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent eed1b1f commit 2e7270b

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

src/node_crypto.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -3359,6 +3359,9 @@ void CipherBase::Init(const char* cipher_type,
33593359
cipher_type);
33603360
}
33613361

3362+
if (mode == EVP_CIPH_WRAP_MODE)
3363+
EVP_CIPHER_CTX_set_flags(&ctx_, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
3364+
33623365
if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
33633366
EVP_CIPHER_CTX_cleanup(&ctx_);
33643367
return env()->ThrowError("Invalid key length");
@@ -3406,13 +3409,18 @@ void CipherBase::InitIv(const char* cipher_type,
34063409
}
34073410

34083411
const int expected_iv_len = EVP_CIPHER_iv_length(cipher_);
3409-
const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == EVP_CIPHER_mode(cipher_));
3412+
const int mode = EVP_CIPHER_mode(cipher_);
3413+
const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == mode);
34103414

34113415
if (is_gcm_mode == false && iv_len != expected_iv_len) {
34123416
return env()->ThrowError("Invalid IV length");
34133417
}
34143418

34153419
EVP_CIPHER_CTX_init(&ctx_);
3420+
3421+
if (mode == EVP_CIPH_WRAP_MODE)
3422+
EVP_CIPHER_CTX_set_flags(&ctx_, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
3423+
34163424
const bool encrypt = (kind_ == kCipher);
34173425
EVP_CipherInit_ex(&ctx_, cipher_, nullptr, nullptr, nullptr, encrypt);
34183426

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

+21
Original file line numberDiff line numberDiff line change
@@ -509,12 +509,33 @@ function testCipher4(key, iv) {
509509
'encryption and decryption with key and iv');
510510
}
511511

512+
513+
function testCipher5(key, iv) {
514+
// Test encryption and decryption with explicit key with aes128-wrap
515+
const plaintext =
516+
'32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
517+
'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
518+
'jAfaFg**';
519+
const cipher = crypto.createCipher('id-aes128-wrap', key);
520+
let ciph = cipher.update(plaintext, 'utf8', 'buffer');
521+
ciph = Buffer.concat([ciph, cipher.final('buffer')]);
522+
523+
const decipher = crypto.createDecipher('id-aes128-wrap', key);
524+
let txt = decipher.update(ciph, 'buffer', 'utf8');
525+
txt += decipher.final('utf8');
526+
527+
assert.strictEqual(txt, plaintext,
528+
'encryption and decryption with key');
529+
}
530+
512531
if (!common.hasFipsCrypto) {
513532
testCipher1('MySecretKey123');
514533
testCipher1(Buffer.from('MySecretKey123'));
515534

516535
testCipher2('0123456789abcdef');
517536
testCipher2(Buffer.from('0123456789abcdef'));
537+
538+
testCipher5(Buffer.from('0123456789abcd0123456789'));
518539
}
519540

520541
testCipher3('0123456789abcd0123456789', '12345678');

test/parallel/test-crypto-cipheriv-decipheriv.js

+24
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,36 @@ function testCipher2(key, iv) {
5555
assert.strictEqual(txt, plaintext, 'encryption/decryption with key and iv');
5656
}
5757

58+
59+
function testCipher3(key, iv) {
60+
// Test encryption and decryption with explicit key and iv.
61+
// AES Key Wrap test vector comes from RFC3394
62+
const plaintext = Buffer.from('00112233445566778899AABBCCDDEEFF', 'hex');
63+
64+
const cipher = crypto.createCipheriv('id-aes128-wrap', key, iv);
65+
let ciph = cipher.update(plaintext, 'utf8', 'buffer');
66+
ciph = Buffer.concat([ciph, cipher.final('buffer')]);
67+
const ciph2 = Buffer.from('1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5',
68+
'hex');
69+
assert(ciph.equals(ciph2));
70+
const decipher = crypto.createDecipheriv('id-aes128-wrap', key, iv);
71+
let deciph = decipher.update(ciph, 'buffer');
72+
deciph = Buffer.concat([deciph, decipher.final()]);
73+
74+
assert(deciph.equals(plaintext), 'encryption/decryption with key and iv');
75+
}
76+
5877
testCipher1('0123456789abcd0123456789', '12345678');
5978
testCipher1('0123456789abcd0123456789', Buffer.from('12345678'));
6079
testCipher1(Buffer.from('0123456789abcd0123456789'), '12345678');
6180
testCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
6281
testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
6382

83+
if (!common.hasFipsCrypto) {
84+
testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'),
85+
Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
86+
}
87+
6488
// Zero-sized IV should be accepted in ECB mode.
6589
crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
6690

0 commit comments

Comments
 (0)