From 495756264affc986f368d714571bc97d6459b0dd Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 18 May 2018 11:05:20 +0200 Subject: [PATCH] crypto: DRY type checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Factor out some common code. The `checkUint()` function will also be used in a follow-up commit that adds scrypt support to core. PR-URL: https://github.com/nodejs/node/pull/20816 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- lib/internal/crypto/pbkdf2.js | 28 +++++++--------------------- lib/internal/crypto/sig.js | 4 ++-- lib/internal/crypto/util.js | 18 +++++++++++++++++- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/internal/crypto/pbkdf2.js b/lib/internal/crypto/pbkdf2.js index 82ea9feb852649..fa004f6c21f409 100644 --- a/lib/internal/crypto/pbkdf2.js +++ b/lib/internal/crypto/pbkdf2.js @@ -4,19 +4,15 @@ const { ERR_INVALID_ARG_TYPE, ERR_INVALID_CALLBACK, ERR_CRYPTO_INVALID_DIGEST, - ERR_OUT_OF_RANGE } = require('internal/errors').codes; const { checkIsArrayBufferView, + checkIsUint, getDefaultEncoding, - toBuf } = require('internal/crypto/util'); const { PBKDF2 } = process.binding('crypto'); -const { - INT_MAX -} = process.binding('constants').crypto; function pbkdf2(password, salt, iterations, keylen, digest, callback) { if (typeof digest === 'function') { @@ -39,22 +35,12 @@ function _pbkdf2(password, salt, iterations, keylen, digest, callback) { if (digest !== null && typeof digest !== 'string') throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest); - password = checkIsArrayBufferView('password', toBuf(password)); - salt = checkIsArrayBufferView('salt', toBuf(salt)); - - if (typeof iterations !== 'number') - throw new ERR_INVALID_ARG_TYPE('iterations', 'number', iterations); - - if (iterations < 0) - throw new ERR_OUT_OF_RANGE('iterations', - 'a non-negative number', - iterations); - - if (typeof keylen !== 'number') - throw new ERR_INVALID_ARG_TYPE('keylen', 'number', keylen); - - if (keylen < 0 || !Number.isInteger(keylen) || keylen > INT_MAX) - throw new ERR_OUT_OF_RANGE('keylen', `>= 0 && <= ${INT_MAX}`, keylen); + password = checkIsArrayBufferView('password', password); + salt = checkIsArrayBufferView('salt', salt); + // FIXME(bnoordhuis) The error message is in fact wrong since |iterations| + // cannot be > INT_MAX. Adjust in the next major release. + iterations = checkIsUint('iterations', iterations, 'a non-negative number'); + keylen = checkIsUint('keylen', keylen); const encoding = getDefaultEncoding(); diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index 1073b83d720098..fa440eb6a3475c 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -77,7 +77,7 @@ Sign.prototype.sign = function sign(options, encoding) { var pssSaltLength = getSaltLength(options); - key = checkIsArrayBufferView('key', toBuf(key)); + key = checkIsArrayBufferView('key', key); var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength); @@ -114,7 +114,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) { var pssSaltLength = getSaltLength(options); - key = checkIsArrayBufferView('key', toBuf(key)); + key = checkIsArrayBufferView('key', key); signature = checkIsArrayBufferView('signature', toBuf(signature, sigEncoding)); diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 59a5d57a1e4f39..cda973addcfe76 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -15,7 +15,8 @@ const { const { ERR_CRYPTO_ENGINE_UNKNOWN, ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, - ERR_INVALID_ARG_TYPE + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE, } = require('internal/errors').codes; const { Buffer } = require('buffer'); const { @@ -25,6 +26,9 @@ const { const { isArrayBufferView } = require('internal/util/types'); +const { + INT_MAX +} = process.binding('constants').crypto; var defaultEncoding = 'buffer'; @@ -84,6 +88,7 @@ function timingSafeEqual(buf1, buf2) { } function checkIsArrayBufferView(name, buffer) { + buffer = toBuf(buffer); if (!isArrayBufferView(buffer)) { throw new ERR_INVALID_ARG_TYPE( name, @@ -94,8 +99,19 @@ function checkIsArrayBufferView(name, buffer) { return buffer; } +function checkIsUint(name, value, errmsg = `>= 0 && <= ${INT_MAX}`) { + if (typeof value !== 'number') + throw new ERR_INVALID_ARG_TYPE(name, 'number', value); + + if (value < 0 || !Number.isInteger(value) || value > INT_MAX) + throw new ERR_OUT_OF_RANGE(name, errmsg, value); + + return value; +} + module.exports = { checkIsArrayBufferView, + checkIsUint, getCiphers, getCurves, getDefaultEncoding,