Skip to content

Commit 30efdad

Browse files
committed
crypto: allow passing null as IV unless required
1 parent bff5d5b commit 30efdad

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

lib/internal/crypto/cipher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function Cipheriv(cipher, key, iv, options) {
182182
}
183183

184184
iv = toBuf(iv);
185-
if (!isArrayBufferView(iv)) {
185+
if (iv !== null && !isArrayBufferView(iv)) {
186186
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'iv',
187187
['string', 'Buffer', 'TypedArray', 'DataView']);
188188
}
@@ -253,7 +253,7 @@ function Decipheriv(cipher, key, iv, options) {
253253
}
254254

255255
iv = toBuf(iv);
256-
if (!isArrayBufferView(iv)) {
256+
if (iv !== null && !isArrayBufferView(iv)) {
257257
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'iv',
258258
['string', 'Buffer', 'TypedArray', 'DataView']);
259259
}

src/node_crypto.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,8 +3090,17 @@ void CipherBase::InitIv(const char* cipher_type,
30903090
const int expected_iv_len = EVP_CIPHER_iv_length(cipher);
30913091
const int mode = EVP_CIPHER_mode(cipher);
30923092
const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == mode);
3093+
const bool has_iv = iv_len >= 0;
30933094

3094-
if (is_gcm_mode == false && iv_len != expected_iv_len) {
3095+
// Throw if no IV was passed and the cipher requires an IV
3096+
if (!has_iv && expected_iv_len != 0) {
3097+
char msg[128];
3098+
snprintf(msg, sizeof(msg), "Missing IV for cipher %s", cipher_type);
3099+
return env()->ThrowError(msg);
3100+
}
3101+
3102+
// Throw if an IV was passed which does not match the cipher's fixed IV length
3103+
if (is_gcm_mode == false && has_iv && iv_len != expected_iv_len) {
30953104
return env()->ThrowError("Invalid IV length");
30963105
}
30973106

@@ -3135,8 +3144,15 @@ void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
31353144
const node::Utf8Value cipher_type(env->isolate(), args[0]);
31363145
ssize_t key_len = Buffer::Length(args[1]);
31373146
const char* key_buf = Buffer::Data(args[1]);
3138-
ssize_t iv_len = Buffer::Length(args[2]);
3139-
const char* iv_buf = Buffer::Data(args[2]);
3147+
ssize_t iv_len;
3148+
const char* iv_buf;
3149+
if (args[2]->IsNullOrUndefined()) {
3150+
iv_buf = nullptr;
3151+
iv_len = -1;
3152+
} else {
3153+
iv_buf = Buffer::Data(args[2]);
3154+
iv_len = Buffer::Length(args[2]);
3155+
}
31403156
cipher->InitIv(*cipher_type, key_buf, key_len, iv_buf, iv_len);
31413157
}
31423158

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function testCipher3(key, iv) {
105105
});
106106

107107
common.expectsError(
108-
() => crypto.createCipheriv('des-ede3-cbc', key, null),
108+
() => crypto.createCipheriv('des-ede3-cbc', key, 10),
109109
{
110110
code: 'ERR_INVALID_ARG_TYPE',
111111
type: TypeError,
@@ -141,7 +141,7 @@ function testCipher3(key, iv) {
141141
});
142142

143143
common.expectsError(
144-
() => crypto.createDecipheriv('des-ede3-cbc', key, null),
144+
() => crypto.createDecipheriv('des-ede3-cbc', key, 10),
145145
{
146146
code: 'ERR_INVALID_ARG_TYPE',
147147
type: TypeError,
@@ -161,8 +161,9 @@ if (!common.hasFipsCrypto) {
161161
Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
162162
}
163163

164-
// Zero-sized IV should be accepted in ECB mode.
164+
// Zero-sized IV or null should be accepted in ECB mode.
165165
crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
166+
crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), null);
166167

167168
const errMessage = /Invalid IV length/;
168169

@@ -186,6 +187,11 @@ for (let n = 0; n < 256; n += 1) {
186187
errMessage);
187188
}
188189

190+
// And so should null be.
191+
assert.throws(() => {
192+
crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), null);
193+
}, /Missing IV for cipher aes-128-cbc/);
194+
189195
// Zero-sized IV should be rejected in GCM mode.
190196
assert.throws(
191197
() => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16),

0 commit comments

Comments
 (0)