Skip to content

Commit c9ea6a9

Browse files
aduh95sxa
authored andcommitted
crypto: validate this value for webcrypto.getRandomValues
PR-URL: #41760 Reviewed-By: Mestery <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 2b35422 commit c9ea6a9

10 files changed

+59
-36
lines changed

benchmark/crypto/webcrypto-digest.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
const common = require('../common.js');
44
const {
55
createHash,
6-
webcrypto: {
7-
subtle,
8-
getRandomValues
9-
}
6+
webcrypto,
107
} = require('crypto');
8+
const { subtle } = webcrypto;
119

1210
const bench = common.createBenchmark(main, {
1311
sync: ['createHash', 'subtle'],
@@ -50,7 +48,7 @@ function measureSubtle(n, data, method) {
5048
}
5149

5250
function main({ n, sync, data, method }) {
53-
data = getRandomValues(Buffer.alloc(data));
51+
data = webcrypto.getRandomValues(Buffer.alloc(data));
5452
switch (sync) {
5553
case 'createHash': return measureLegacy(n, data, method);
5654
case 'subtle': return measureSubtle(n, data, method);

doc/api/webcrypto.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ async function generateRsaKey(modulusLength = 2048, hash = 'SHA-256') {
128128
### Encryption and decryption
129129

130130
```js
131-
const { subtle, getRandomValues } = require('crypto').webcrypto;
131+
const crypto = require('crypto').webcrypto;
132132

133133
async function aesEncrypt(plaintext) {
134134
const ec = new TextEncoder();
135135
const key = await generateAesKey();
136-
const iv = getRandomValues(new Uint8Array(16));
136+
const iv = crypto.getRandomValues(new Uint8Array(16));
137137

138-
const ciphertext = await subtle.encrypt({
138+
const ciphertext = await crypto.subtle.encrypt({
139139
name: 'AES-CBC',
140140
iv,
141141
}, key, ec.encode(plaintext));
@@ -149,7 +149,7 @@ async function aesEncrypt(plaintext) {
149149

150150
async function aesDecrypt(ciphertext, key, iv) {
151151
const dec = new TextDecoder();
152-
const plaintext = await subtle.decrypt({
152+
const plaintext = await crypto.subtle.decrypt({
153153
name: 'AES-CBC',
154154
iv,
155155
}, key, ciphertext);

lib/internal/crypto/webcrypto.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {
55
JSONParse,
66
JSONStringify,
77
ObjectDefineProperties,
8+
ReflectApply,
89
SafeSet,
910
SymbolToStringTag,
1011
StringPrototypeRepeat,
@@ -31,6 +32,7 @@ const { TextDecoder, TextEncoder } = require('internal/encoding');
3132
const {
3233
codes: {
3334
ERR_INVALID_ARG_TYPE,
35+
ERR_INVALID_THIS,
3436
}
3537
} = require('internal/errors');
3638

@@ -64,7 +66,7 @@ const {
6466
} = require('internal/util');
6567

6668
const {
67-
getRandomValues,
69+
getRandomValues: _getRandomValues,
6870
randomUUID: _randomUUID,
6971
} = require('internal/crypto/random');
7072

@@ -695,6 +697,13 @@ class Crypto {
695697
}
696698
const crypto = new Crypto();
697699

700+
function getRandomValues(array) {
701+
if (!(this instanceof Crypto)) {
702+
throw new ERR_INVALID_THIS('Crypto');
703+
}
704+
return ReflectApply(_getRandomValues, this, arguments);
705+
}
706+
698707
ObjectDefineProperties(
699708
Crypto.prototype, {
700709
[SymbolToStringTag]: {

test/parallel/test-webcrypto-derivebits-ecdh.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { subtle, getRandomValues } = require('crypto').webcrypto;
9+
const { webcrypto } = require('crypto');
10+
const { subtle } = webcrypto;
1011

1112
const kTests = [
1213
{
@@ -250,7 +251,7 @@ async function prepareKeys() {
250251

251252
{
252253
// Public is a secret key
253-
const keyData = getRandomValues(new Uint8Array(32));
254+
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
254255
const key = await subtle.importKey(
255256
'raw',
256257
keyData,

test/parallel/test-webcrypto-derivekey-ecdh.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { subtle, getRandomValues } = require('crypto').webcrypto;
9+
const { webcrypto } = require('crypto');
10+
const { subtle } = webcrypto;
1011

1112
const kTests = [
1213
{
@@ -226,7 +227,7 @@ async function prepareKeys() {
226227

227228
{
228229
// Public is a secret key
229-
const keyData = getRandomValues(new Uint8Array(32));
230+
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
230231
const key = await subtle.importKey(
231232
'raw',
232233
keyData,

test/parallel/test-webcrypto-encrypt-decrypt-aes.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { getRandomValues, subtle } = require('crypto').webcrypto;
9+
const { webcrypto } = require('crypto');
10+
const { subtle } = webcrypto;
1011

1112
async function testEncrypt({ keyBuffer, algorithm, plaintext, result }) {
1213
// Using a copy of plaintext to prevent tampering of the original
@@ -213,8 +214,8 @@ async function testDecrypt({ keyBuffer, algorithm, result }) {
213214
['encrypt', 'decrypt'],
214215
);
215216

216-
const iv = getRandomValues(new Uint8Array(12));
217-
const aad = getRandomValues(new Uint8Array(32));
217+
const iv = webcrypto.getRandomValues(new Uint8Array(12));
218+
const aad = webcrypto.getRandomValues(new Uint8Array(32));
218219

219220
const encrypted = await subtle.encrypt(
220221
{
@@ -224,7 +225,7 @@ async function testDecrypt({ keyBuffer, algorithm, result }) {
224225
tagLength: 128
225226
},
226227
secretKey,
227-
getRandomValues(new Uint8Array(32))
228+
webcrypto.getRandomValues(new Uint8Array(32))
228229
);
229230

230231
await subtle.decrypt(

test/parallel/test-webcrypto-encrypt-decrypt.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { subtle, getRandomValues } = require('crypto').webcrypto;
9+
const { webcrypto } = require('crypto');
10+
const { subtle } = webcrypto;
1011

1112
// This is only a partial test. The WebCrypto Web Platform Tests
1213
// will provide much greater coverage.
1314

1415
// Test Encrypt/Decrypt RSA-OAEP
1516
{
16-
const buf = getRandomValues(new Uint8Array(50));
17+
const buf = webcrypto.getRandomValues(new Uint8Array(50));
1718

1819
async function test() {
1920
const ec = new TextEncoder();
@@ -44,8 +45,8 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
4445

4546
// Test Encrypt/Decrypt AES-CTR
4647
{
47-
const buf = getRandomValues(new Uint8Array(50));
48-
const counter = getRandomValues(new Uint8Array(16));
48+
const buf = webcrypto.getRandomValues(new Uint8Array(50));
49+
const counter = webcrypto.getRandomValues(new Uint8Array(16));
4950

5051
async function test() {
5152
const key = await subtle.generateKey({
@@ -71,8 +72,8 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
7172

7273
// Test Encrypt/Decrypt AES-CBC
7374
{
74-
const buf = getRandomValues(new Uint8Array(50));
75-
const iv = getRandomValues(new Uint8Array(16));
75+
const buf = webcrypto.getRandomValues(new Uint8Array(50));
76+
const iv = webcrypto.getRandomValues(new Uint8Array(16));
7677

7778
async function test() {
7879
const key = await subtle.generateKey({
@@ -98,8 +99,8 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
9899

99100
// Test Encrypt/Decrypt AES-GCM
100101
{
101-
const buf = getRandomValues(new Uint8Array(50));
102-
const iv = getRandomValues(new Uint8Array(12));
102+
const buf = webcrypto.getRandomValues(new Uint8Array(50));
103+
const iv = webcrypto.getRandomValues(new Uint8Array(12));
103104

104105
async function test() {
105106
const key = await subtle.generateKey({

test/parallel/test-webcrypto-export-import.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ if (!common.hasCrypto)
66
common.skip('missing crypto');
77

88
const assert = require('assert');
9-
const { subtle, getRandomValues } = require('crypto').webcrypto;
9+
const { webcrypto } = require('crypto');
10+
const { subtle } = webcrypto;
1011

1112
{
1213
async function test() {
13-
const keyData = getRandomValues(new Uint8Array(32));
14+
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
1415
await Promise.all([1, null, undefined, {}, []].map((format) =>
1516
assert.rejects(
1617
subtle.importKey(format, keyData, {}, false, ['wrapKey']), {
@@ -82,7 +83,7 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
8283
// Import/Export HMAC Secret Key
8384
{
8485
async function test() {
85-
const keyData = getRandomValues(new Uint8Array(32));
86+
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
8687
const key = await subtle.importKey(
8788
'raw',
8889
keyData, {
@@ -112,7 +113,7 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
112113
// Import/Export AES Secret Key
113114
{
114115
async function test() {
115-
const keyData = getRandomValues(new Uint8Array(32));
116+
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
116117
const key = await subtle.importKey(
117118
'raw',
118119
keyData, {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
if (!common.hasCrypto)
6+
common.skip('missing crypto');
7+
8+
const assert = require('assert');
9+
const { getRandomValues } = require('crypto').webcrypto;
10+
11+
assert.throws(() => getRandomValues(new Uint8Array()), { code: 'ERR_INVALID_THIS' });

test/parallel/test-webcrypto-random.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ if (!common.hasCrypto)
77

88
const { Buffer } = require('buffer');
99
const assert = require('assert');
10-
const { getRandomValues } = require('crypto').webcrypto;
10+
const { webcrypto } = require('crypto');
1111

1212
[
1313
undefined, null, '', 1, {}, [],
@@ -16,14 +16,14 @@ const { getRandomValues } = require('crypto').webcrypto;
1616
new DataView(new ArrayBuffer(1)),
1717
].forEach((i) => {
1818
assert.throws(
19-
() => getRandomValues(i),
19+
() => webcrypto.getRandomValues(i),
2020
{ name: 'TypeMismatchError', code: 17 },
2121
);
2222
});
2323

2424
{
2525
const buf = new Uint8Array(0);
26-
getRandomValues(buf);
26+
webcrypto.getRandomValues(buf);
2727
}
2828

2929
const intTypedConstructors = [
@@ -41,15 +41,15 @@ const intTypedConstructors = [
4141
for (const ctor of intTypedConstructors) {
4242
const buf = new ctor(10);
4343
const before = Buffer.from(buf.buffer).toString('hex');
44-
getRandomValues(buf);
44+
webcrypto.getRandomValues(buf);
4545
const after = Buffer.from(buf.buffer).toString('hex');
4646
assert.notStrictEqual(before, after);
4747
}
4848

4949
{
5050
const buf = new Uint16Array(10);
5151
const before = Buffer.from(buf).toString('hex');
52-
getRandomValues(buf);
52+
webcrypto.getRandomValues(buf);
5353
const after = Buffer.from(buf).toString('hex');
5454
assert.notStrictEqual(before, after);
5555
}
@@ -63,7 +63,7 @@ for (const ctor of intTypedConstructors) {
6363
}
6464

6565
if (kData !== undefined) {
66-
assert.throws(() => getRandomValues(kData), {
66+
assert.throws(() => webcrypto.getRandomValues(kData), {
6767
code: 22
6868
});
6969
}

0 commit comments

Comments
 (0)