Skip to content

Commit

Permalink
crypto: pass all webcrypto WPTs
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Jul 2, 2022
1 parent c753f27 commit 716caf7
Show file tree
Hide file tree
Showing 43 changed files with 1,631 additions and 169 deletions.
12 changes: 5 additions & 7 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ const {
generateKey,
} = require('internal/crypto/keygen');

const {
validateInteger,
validateOneOf,
} = require('internal/validators');

const kMaxCounterLength = 128;
const kTagLengths = [32, 64, 96, 104, 112, 120, 128];

Expand Down Expand Up @@ -227,8 +222,11 @@ function aesCipher(mode, key, data, algorithm) {

async function aesGenerateKey(algorithm, extractable, keyUsages) {
const { name, length } = algorithm;
validateInteger(length, 'algorithm.length');
validateOneOf(length, 'algorithm.length', kAesKeyLengths);
if (!ArrayPrototypeIncludes(kAesKeyLengths, length)) {
throw lazyDOMException(
'AES key length must be 128, 192, or 256 bits',
'OperationError');
}

const checkUsages = ['wrapKey', 'unwrapKey'];
if (name !== 'AES-KW')
Expand Down
29 changes: 14 additions & 15 deletions lib/internal/crypto/ec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayPrototypeIncludes,
ObjectKeys,
Promise,
SafeSet,
Expand All @@ -17,11 +18,6 @@ const {
kSigEncP1363,
} = internalBinding('crypto');

const {
validateOneOf,
validateString,
} = require('internal/validators');

const {
codes: {
ERR_MISSING_OPTION,
Expand Down Expand Up @@ -88,11 +84,12 @@ function createECPublicKeyRaw(namedCurve, keyData) {

async function ecGenerateKey(algorithm, extractable, keyUsages) {
const { name, namedCurve } = algorithm;
validateString(namedCurve, 'algorithm.namedCurve');
validateOneOf(
namedCurve,
'algorithm.namedCurve',
ObjectKeys(kNamedCurveAliases));

if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) {
throw lazyDOMException(
'Unrecognized namedCurve',
'NotSupportedError');
}

const usageSet = new SafeSet(keyUsages);
switch (name) {
Expand Down Expand Up @@ -168,11 +165,13 @@ async function ecImportKey(
keyUsages) {

const { name, namedCurve } = algorithm;
validateString(namedCurve, 'algorithm.namedCurve');
validateOneOf(
namedCurve,
'algorithm.namedCurve',
ObjectKeys(kNamedCurveAliases));

if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) {
throw lazyDOMException(
'Unrecognized namedCurve',
'NotSupportedError');
}

let keyObject;
const usagesSet = new SafeSet(keyUsages);
switch (format) {
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/crypto/hkdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ function hkdfSync(hash, key, salt, info, length) {
}

async function hkdfDeriveBits(algorithm, baseKey, length) {
validateUint32(length, 'length');
const { hash } = algorithm;
const salt = getArrayBufferOrView(algorithm.salt, 'algorithm.salt');
const info = getArrayBufferOrView(algorithm.info, 'algorithm.info');
Expand All @@ -153,6 +152,9 @@ async function hkdfDeriveBits(algorithm, baseKey, length) {
if (length !== undefined) {
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
validateUint32(length, 'length');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
Expand Down
3 changes: 0 additions & 3 deletions lib/internal/crypto/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const {
ERR_ILLEGAL_CONSTRUCTOR,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_OUT_OF_RANGE,
}
} = require('internal/errors');

Expand Down Expand Up @@ -588,8 +587,6 @@ function prepareSecretKey(key, encoding, bufferOnly = false) {

function createSecretKey(key, encoding) {
key = prepareSecretKey(key, encoding, true);
if (key.byteLength === 0)
throw new ERR_OUT_OF_RANGE('key.byteLength', '> 0', key.byteLength);
const handle = new KeyObjectHandle();
handle.init(kKeyTypeSecret, key);
return new SecretKeyObject(handle);
Expand Down
3 changes: 0 additions & 3 deletions lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ async function hmacImportKey(
case 'raw': {
const checkLength = keyData.byteLength * 8;

if (checkLength === 0 || algorithm.length === 0)
throw lazyDOMException('Zero-length key is not supported', 'DataError');

// The Web Crypto spec allows for key lengths that are not multiples of
// 8. We don't. Our check here is stricter than that defined by the spec
// in that we require that algorithm.length match keyData.length * 8 if
Expand Down
10 changes: 8 additions & 2 deletions lib/internal/crypto/pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,16 @@ function check(password, salt, iterations, keylen, digest) {
}

async function pbkdf2DeriveBits(algorithm, baseKey, length) {
validateUint32(length, 'length');
const { iterations } = algorithm;
let { hash } = algorithm;
const salt = getArrayBufferOrView(algorithm.salt, 'algorithm.salt');
if (hash === undefined)
throw new ERR_MISSING_OPTION('algorithm.hash');
validateInteger(iterations, 'algorithm.iterations', 1);
validateInteger(iterations, 'algorithm.iterations');
if (iterations === 0)
throw lazyDOMException(
'iterations cannot be zero',
'OperationError');

hash = normalizeHashName(hash.name);

Expand All @@ -114,6 +117,9 @@ async function pbkdf2DeriveBits(algorithm, baseKey, length) {
if (length !== undefined) {
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
validateUint32(length, 'length');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
Expand Down
6 changes: 5 additions & 1 deletion lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,11 @@ const validateByteSource = hideStackFrames((val, name) => {
});

function onDone(resolve, reject, err, result) {
if (err) return reject(err);
if (err) {
return reject(lazyDOMException(
'The operation failed for an operation-specific reason',
'OperationError'));
}
resolve(result);
}

Expand Down
3 changes: 0 additions & 3 deletions lib/internal/crypto/webcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,6 @@ async function importGenericSecretKey(

const checkLength = keyData.byteLength * 8;

if (checkLength === 0 || length === 0)
throw lazyDOMException('Zero-length key is not supported', 'DataError');

// The Web Crypto spec allows for key lengths that are not multiples of
// 8. We don't. Our check here is stricter than that defined by the spec
// in that we require that algorithm.length match keyData.length * 8 if
Expand Down
39 changes: 31 additions & 8 deletions src/crypto/crypto_hkdf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,43 @@ bool HKDFTraits::DeriveBits(
EVPKeyCtxPointer ctx =
EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
if (!ctx || !EVP_PKEY_derive_init(ctx.get()) ||
!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), params.digest) ||
!EVP_PKEY_CTX_set1_hkdf_salt(
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
!EVP_PKEY_CTX_set1_hkdf_key(
ctx.get(),
reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
params.key->GetSymmetricKeySize()) ||
!EVP_PKEY_CTX_add1_hkdf_info(
ctx.get(), params.info.data<unsigned char>(), params.info.size())) {
return false;
}

if (params.key->GetSymmetricKeySize() != 0) {
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
!EVP_PKEY_CTX_set1_hkdf_salt(
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(),
reinterpret_cast<const unsigned char*>(
params.key->GetSymmetricKey()),
params.key->GetSymmetricKeySize())) {
return false;
}
} else {
unsigned int len = EVP_MD_size(params.digest);
uint8_t tempKey[len]; // NOLINT(runtime/arrays)
if (params.salt.size()) {
HMAC(params.digest,
params.salt.data(),
params.salt.size(),
nullptr,
0,
tempKey,
&len);
} else {
HMAC(params.digest, new char[len]{}, len, nullptr, 0, tempKey, &len);
}
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), tempKey, len)) {
return false;
}
}

size_t length = params.length;
ByteSource::Builder buf(length);
if (EVP_PKEY_derive(ctx.get(), buf.data<unsigned char>(), &length) <= 0)
Expand Down
1 change: 0 additions & 1 deletion src/crypto/crypto_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,6 @@ void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
}

std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
CHECK(key);
return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
}

Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/wpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Last update:
- user-timing: https:/web-platform-tests/wpt/tree/df24fb604e/user-timing
- wasm/jsapi: https:/web-platform-tests/wpt/tree/1dd414c796/wasm/jsapi
- wasm/webapi: https:/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi
- WebCryptoAPI: https:/web-platform-tests/wpt/tree/cdd0f03df4/WebCryptoAPI
- WebCryptoAPI: https:/web-platform-tests/wpt/tree/edca84af42/WebCryptoAPI
- webidl/ecmascript-binding/es-exceptions: https:/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions

[Web Platform Tests]: https:/web-platform-tests/wpt
Expand Down
Loading

0 comments on commit 716caf7

Please sign in to comment.