Skip to content

Commit

Permalink
crypto: validate this value for webcrypto.getRandomValues
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 committed Jan 29, 2022
1 parent 05e9cb6 commit 62e34b5
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 27 deletions.
11 changes: 10 additions & 1 deletion lib/internal/crypto/webcrypto.js
Expand Up @@ -5,6 +5,7 @@ const {
JSONParse,
JSONStringify,
ObjectDefineProperties,
ReflectApply,
SafeSet,
SymbolToStringTag,
StringPrototypeRepeat,
Expand All @@ -31,6 +32,7 @@ const { TextDecoder, TextEncoder } = require('internal/encoding');
const {
codes: {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_THIS,
}
} = require('internal/errors');

Expand Down Expand Up @@ -63,7 +65,7 @@ const {
} = require('internal/util');

const {
getRandomValues,
getRandomValues: _getRandomValues,
randomUUID: _randomUUID,
} = require('internal/crypto/random');

Expand Down Expand Up @@ -690,6 +692,13 @@ const subtle = new SubtleCrypto();
class Crypto {}
const crypto = new Crypto();

function getRandomValues(array) {
if (!(this instanceof Crypto)) {
throw new ERR_INVALID_THIS('Crypto');
}
return ReflectApply(_getRandomValues, this, arguments);
}

ObjectDefineProperties(
Crypto.prototype, {
[SymbolToStringTag]: {
Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-webcrypto-derivebits-ecdh.js
Expand Up @@ -6,7 +6,8 @@ if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { subtle, getRandomValues } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

const kTests = [
{
Expand Down Expand Up @@ -250,7 +251,7 @@ async function prepareKeys() {

{
// Public is a secret key
const keyData = getRandomValues(new Uint8Array(32));
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData,
Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-webcrypto-derivekey-ecdh.js
Expand Up @@ -6,7 +6,8 @@ if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { subtle, getRandomValues } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

const kTests = [
{
Expand Down Expand Up @@ -226,7 +227,7 @@ async function prepareKeys() {

{
// Public is a secret key
const keyData = getRandomValues(new Uint8Array(32));
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData,
Expand Down
9 changes: 5 additions & 4 deletions test/parallel/test-webcrypto-encrypt-decrypt-aes.js
Expand Up @@ -6,7 +6,8 @@ if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { getRandomValues, subtle } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

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

const iv = getRandomValues(new Uint8Array(12));
const aad = getRandomValues(new Uint8Array(32));
const iv = webcrypto.getRandomValues(new Uint8Array(12));
const aad = webcrypto.getRandomValues(new Uint8Array(32));

const encrypted = await subtle.encrypt(
{
Expand All @@ -224,7 +225,7 @@ async function testDecrypt({ keyBuffer, algorithm, result }) {
tagLength: 128
},
secretKey,
getRandomValues(new Uint8Array(32))
webcrypto.getRandomValues(new Uint8Array(32))
);

await subtle.decrypt(
Expand Down
17 changes: 9 additions & 8 deletions test/parallel/test-webcrypto-encrypt-decrypt.js
Expand Up @@ -6,14 +6,15 @@ if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { subtle, getRandomValues } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

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

// Test Encrypt/Decrypt RSA-OAEP
{
const buf = getRandomValues(new Uint8Array(50));
const buf = webcrypto.getRandomValues(new Uint8Array(50));

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

// Test Encrypt/Decrypt AES-CTR
{
const buf = getRandomValues(new Uint8Array(50));
const counter = getRandomValues(new Uint8Array(16));
const buf = webcrypto.getRandomValues(new Uint8Array(50));
const counter = webcrypto.getRandomValues(new Uint8Array(16));

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

// Test Encrypt/Decrypt AES-CBC
{
const buf = getRandomValues(new Uint8Array(50));
const iv = getRandomValues(new Uint8Array(16));
const buf = webcrypto.getRandomValues(new Uint8Array(50));
const iv = webcrypto.getRandomValues(new Uint8Array(16));

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

// Test Encrypt/Decrypt AES-GCM
{
const buf = getRandomValues(new Uint8Array(50));
const iv = getRandomValues(new Uint8Array(12));
const buf = webcrypto.getRandomValues(new Uint8Array(50));
const iv = webcrypto.getRandomValues(new Uint8Array(12));

async function test() {
const key = await subtle.generateKey({
Expand Down
9 changes: 5 additions & 4 deletions test/parallel/test-webcrypto-export-import.js
Expand Up @@ -6,11 +6,12 @@ if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { subtle, getRandomValues } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

{
async function test() {
const keyData = getRandomValues(new Uint8Array(32));
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
await Promise.all([1, null, undefined, {}, []].map((format) =>
assert.rejects(
subtle.importKey(format, keyData, {}, false, ['wrapKey']), {
Expand Down Expand Up @@ -82,7 +83,7 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
// Import/Export HMAC Secret Key
{
async function test() {
const keyData = getRandomValues(new Uint8Array(32));
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData, {
Expand Down Expand Up @@ -112,7 +113,7 @@ const { subtle, getRandomValues } = require('crypto').webcrypto;
// Import/Export AES Secret Key
{
async function test() {
const keyData = getRandomValues(new Uint8Array(32));
const keyData = webcrypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData, {
Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-webcrypto-getRandomValues.js
@@ -0,0 +1,11 @@
'use strict';

const common = require('../common');

if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { getRandomValues } = require('crypto').webcrypto;

assert.throws(() => getRandomValues(new Uint8Array()), { code: 'ERR_INVALID_THIS' });
12 changes: 6 additions & 6 deletions test/parallel/test-webcrypto-random.js
Expand Up @@ -7,7 +7,7 @@ if (!common.hasCrypto)

const { Buffer } = require('buffer');
const assert = require('assert');
const { getRandomValues } = require('crypto').webcrypto;
const { webcrypto } = require('crypto');

[
undefined, null, '', 1, {}, [],
Expand All @@ -16,14 +16,14 @@ const { getRandomValues } = require('crypto').webcrypto;
new DataView(new ArrayBuffer(1)),
].forEach((i) => {
assert.throws(
() => getRandomValues(i),
() => webcrypto.getRandomValues(i),
{ name: 'TypeMismatchError', code: 17 },
);
});

{
const buf = new Uint8Array(0);
getRandomValues(buf);
webcrypto.getRandomValues(buf);
}

const intTypedConstructors = [
Expand All @@ -41,15 +41,15 @@ const intTypedConstructors = [
for (const ctor of intTypedConstructors) {
const buf = new ctor(10);
const before = Buffer.from(buf.buffer).toString('hex');
getRandomValues(buf);
webcrypto.getRandomValues(buf);
const after = Buffer.from(buf.buffer).toString('hex');
assert.notStrictEqual(before, after);
}

{
const buf = new Uint16Array(10);
const before = Buffer.from(buf).toString('hex');
getRandomValues(buf);
webcrypto.getRandomValues(buf);
const after = Buffer.from(buf).toString('hex');
assert.notStrictEqual(before, after);
}
Expand All @@ -63,7 +63,7 @@ for (const ctor of intTypedConstructors) {
}

if (kData !== undefined) {
assert.throws(() => getRandomValues(kData), {
assert.throws(() => webcrypto.getRandomValues(kData), {
code: 22
});
}
Expand Down

0 comments on commit 62e34b5

Please sign in to comment.