Skip to content

Commit

Permalink
crypto: allocate more memory for cipher.update()
Browse files Browse the repository at this point in the history
For key wrapping algorithms, calling EVP_CipherUpdate() with null output
could obtain the size for the ciphertext. Then use the returned size to
allocate output buffer. Also add a test case to verify des3-wrap.

Signed-off-by: Yihong Wang <yh.wang@ibm.com>

PR-URL: #20370
Fixes: #19655
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
yhwang authored and tniessen committed May 4, 2018
1 parent cd8ed1c commit f7cdeba
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3023,14 +3023,28 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
auth_tag_set_ = true;
}

*out_len = len + EVP_CIPHER_CTX_block_size(ctx_);
*out = Malloc<unsigned char>(static_cast<size_t>(*out_len));
*out_len = 0;
int buff_len = len + EVP_CIPHER_CTX_block_size(ctx_);
// For key wrapping algorithms, get output size by calling
// EVP_CipherUpdate() with null output.
if (mode == EVP_CIPH_WRAP_MODE &&
EVP_CipherUpdate(ctx_,
nullptr,
&buff_len,
reinterpret_cast<const unsigned char*>(data),
len) != 1) {
return kErrorState;
}

*out = Malloc<unsigned char>(buff_len);
int r = EVP_CipherUpdate(ctx_,
*out,
out_len,
reinterpret_cast<const unsigned char*>(data),
len);

CHECK_LE(*out_len, buff_len);

// When in CCM mode, EVP_CipherUpdate will fail if the authentication tag is
// invalid. In that case, remember the error and throw in final().
if (!r && kind_ == kDecipher && mode == EVP_CIPH_CCM_MODE) {
Expand Down
25 changes: 25 additions & 0 deletions test/parallel/test-crypto-des3-wrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const crypto = require('crypto');

// Test case for des-ede3 wrap/unwrap. des3-wrap needs extra 2x blocksize
// then plaintext to store ciphertext.
const test = {
key: Buffer.from('3c08e25be22352910671cfe4ba3652b1220a8a7769b490ba', 'hex'),
iv: Buffer.alloc(0),
plaintext: '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBG' +
'WWELweCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZU' +
'JjAfaFg**'
};

const cipher = crypto.createCipheriv('des3-wrap', test.key, test.iv);
const ciphertext = cipher.update(test.plaintext, 'utf8');

const decipher = crypto.createDecipheriv('des3-wrap', test.key, test.iv);
const msg = decipher.update(ciphertext, 'buffer', 'utf8');

assert.strictEqual(msg, test.plaintext);

0 comments on commit f7cdeba

Please sign in to comment.