GeezerVison is showing github.com — crypto: fix argument validation in crypto.timingSafeEqual fast path · nodejs/node@ad376c3
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_timing.cc +14Lines changed: 14 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -56,6 +56,20 @@ bool FastTimingSafeEqual(Local<Value> receiver, | 56 | 56 | // NOLINTNEXTLINE(runtime/references) | 57 | 57 | FastApiCallbackOptions& options) { | 58 | 58 | HandleScope scope(options.isolate); | | 59 | + if (!IsAnyBufferSource(a_obj)) { | | 60 | + TRACK_V8_FAST_API_CALL("crypto.timingSafeEqual.error"); | | 61 | + THROW_ERR_INVALID_ARG_TYPE(options.isolate, | | 62 | + "The \"buf1\" argument must be an instance of " | | 63 | + "ArrayBuffer, Buffer, TypedArray, or DataView."); | | 64 | + return false; | | 65 | + } | | 66 | + if (!IsAnyBufferSource(b_obj)) { | | 67 | + TRACK_V8_FAST_API_CALL("crypto.timingSafeEqual.error"); | | 68 | + THROW_ERR_INVALID_ARG_TYPE(options.isolate, | | 69 | + "The \"buf2\" argument must be an instance of " | | 70 | + "ArrayBuffer, Buffer, TypedArray, or DataView."); | | 71 | + return false; | | 72 | + } | 59 | 73 | ArrayBufferViewContents<uint8_t> a(a_obj); | 60 | 74 | ArrayBufferViewContents<uint8_t> b(b_obj); | 61 | 75 | if (a.length() != b.length()) { | |
Collapse file Copy file name to clipboard +40Lines changed: 40 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Test v8 fast path for crypto.timingSafeEqual works correctly. | | 2 | +// Flags: --expose-internals --allow-natives-syntax | | 3 | +'use strict'; | | 4 | + | | 5 | +const common = require('../common'); | | 6 | + | | 7 | +if (!common.hasCrypto) | | 8 | + common.skip('missing crypto'); | | 9 | + | | 10 | +const assert = require('assert'); | | 11 | +const crypto = require('crypto'); | | 12 | + | | 13 | +// V8 Fast API | | 14 | +const foo = Buffer.from('foo'); | | 15 | +const bar = Buffer.from('bar'); | | 16 | +const longer = Buffer.from('longer'); | | 17 | +function testFastPath(buf1, buf2) { | | 18 | + return crypto.timingSafeEqual(buf1, buf2); | | 19 | +} | | 20 | +eval('%PrepareFunctionForOptimization(testFastPath)'); | | 21 | +assert.strictEqual(testFastPath(foo, bar), false); | | 22 | +eval('%OptimizeFunctionOnNextCall(testFastPath)'); | | 23 | +assert.strictEqual(testFastPath(foo, bar), false); | | 24 | +assert.strictEqual(testFastPath(foo, foo), true); | | 25 | +assert.throws(() => testFastPath(foo, longer), { | | 26 | + code: 'ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', | | 27 | +}); | | 28 | +assert.throws(() => testFastPath(foo, ''), { | | 29 | + code: 'ERR_INVALID_ARG_TYPE', | | 30 | +}); | | 31 | +assert.throws(() => testFastPath('', ''), { | | 32 | + code: 'ERR_INVALID_ARG_TYPE', | | 33 | +}); | | 34 | + | | 35 | +if (common.isDebug) { | | 36 | + const { internalBinding } = require('internal/test/binding'); | | 37 | + const { getV8FastApiCallCount } = internalBinding('debug'); | | 38 | + assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.ok'), 2); | | 39 | + assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.error'), 3); | | 40 | +} |
Collapse file Copy file name to clipboardExpand all lines: test/sequential/test-crypto-timing-safe-equal.js +1-26Lines changed: 1 addition & 26 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | | -// Flags: --expose-internals --no-warnings --allow-natives-syntax | | 1 | +// Flags: --no-warnings | 2 | 2 | 'use strict'; | 3 | 3 | const common = require('../common'); | 4 | 4 | if (!common.hasCrypto) | @@ -92,28 +92,3 @@ assert.throws( | 92 | 92 | name: 'TypeError', | 93 | 93 | } | 94 | 94 | ); | 95 | | - | 96 | | -{ | 97 | | - // V8 Fast API | 98 | | - const foo = Buffer.from('foo'); | 99 | | - const bar = Buffer.from('bar'); | 100 | | - const longer = Buffer.from('longer'); | 101 | | - function testFastPath(buf1, buf2) { | 102 | | - return crypto.timingSafeEqual(buf1, buf2); | 103 | | - } | 104 | | - eval('%PrepareFunctionForOptimization(testFastPath)'); | 105 | | - assert.strictEqual(testFastPath(foo, bar), false); | 106 | | - eval('%OptimizeFunctionOnNextCall(testFastPath)'); | 107 | | - assert.strictEqual(testFastPath(foo, bar), false); | 108 | | - assert.strictEqual(testFastPath(foo, foo), true); | 109 | | - assert.throws(() => testFastPath(foo, longer), { | 110 | | - code: 'ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', | 111 | | - }); | 112 | | - | 113 | | - if (common.isDebug) { | 114 | | - const { internalBinding } = require('internal/test/binding'); | 115 | | - const { getV8FastApiCallCount } = internalBinding('debug'); | 116 | | - assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.ok'), 2); | 117 | | - assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.error'), 1); | 118 | | - } | 119 | | -} |
|