Skip to content

Commit 9586d3d

Browse files
committed
Define the deriveBits length parameter as optional
https://bugs.webkit.org/show_bug.cgi?id=276394 Reviewed by Youenn Fablet and Nitin Mahendru. The PR#345 [1] to the WebCryptoAPI spec defines now the 'length' parameter as optional, defaulting to 'null'. This change tries to solve a long-standing interoperability issue in the deriveBits operation. This patch implements the required changes in the IDL so that the 'length' parameter is declared as optional, with 'null' as default value when omitted. The affected algorithms (ECDH, HKDF, PBKDF2 and X25519) are adapted to the parameter's new type. The PR#43400 [2] defined tests for the new behavior of the afected algorithms, which they all pass now. [1] w3c/webcrypto#345 [2] web-platform-tests/wpt#43400 * LayoutTests/crypto/subtle/derive-bits-malformed-parameters-expected.txt: * LayoutTests/crypto/subtle/derive-bits-malformed-parameters.html: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any.worker-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/idlharness.https.any-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/idlharness.https.any.worker-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/interfaces/WebCryptoAPI.idl: * Source/WebCore/crypto/CryptoAlgorithm.cpp: (WebCore::CryptoAlgorithm::deriveBits): * Source/WebCore/crypto/CryptoAlgorithm.h: * Source/WebCore/crypto/SubtleCrypto.cpp: (WebCore::SubtleCrypto::deriveKey): (WebCore::SubtleCrypto::deriveBits): * Source/WebCore/crypto/SubtleCrypto.h: * Source/WebCore/crypto/SubtleCrypto.idl: * Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.cpp: (WebCore::CryptoAlgorithmECDH::deriveBits): * Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.h: * Source/WebCore/crypto/algorithms/CryptoAlgorithmHKDF.cpp: (WebCore::CryptoAlgorithmHKDF::deriveBits): * Source/WebCore/crypto/algorithms/CryptoAlgorithmHKDF.h: * Source/WebCore/crypto/algorithms/CryptoAlgorithmPBKDF2.cpp: (WebCore::CryptoAlgorithmPBKDF2::deriveBits): * Source/WebCore/crypto/algorithms/CryptoAlgorithmPBKDF2.h: * Source/WebCore/crypto/algorithms/CryptoAlgorithmX25519.cpp: (WebCore::CryptoAlgorithmX25519::deriveBits): * Source/WebCore/crypto/algorithms/CryptoAlgorithmX25519.h: Canonical link: https://commits.webkit.org/281240@main
1 parent 43764db commit 9586d3d

20 files changed

+39
-41
lines changed

LayoutTests/crypto/subtle/derive-bits-malformed-parameters-expected.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
55

66
PASS crypto.subtle.deriveBits() rejected promise with TypeError: Not enough arguments.
77
PASS crypto.subtle.deriveBits(1) rejected promise with TypeError: Not enough arguments.
8-
PASS crypto.subtle.deriveBits(1, 2) rejected promise with TypeError: Not enough arguments.
98
PASS crypto.subtle.deriveBits({ name:"ECDH", public:wrongKey }, wrongKey, 128) rejected promise with InvalidAccessError: CryptoKey doesn't match AlgorithmIdentifier.
109
PASS crypto.subtle.deriveBits({ name:"ECDH", public:wrongKey }, wrongKey, 128) rejected promise with InvalidAccessError: CryptoKey doesn't support bits derivation.
1110
PASS successfullyParsed is true

LayoutTests/crypto/subtle/derive-bits-malformed-parameters.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
// Not enough arguments.
3333
shouldReject('crypto.subtle.deriveBits()');
3434
shouldReject('crypto.subtle.deriveBits(1)');
35-
shouldReject('crypto.subtle.deriveBits(1, 2)');
3635

3736
crypto.subtle.importKey("raw", rawKey, hmacImportParams, extractable, ["sign", "verify"]).then(function(result) {
3837
wrongKey = result;

LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any-expected.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ PASS HKDF derivation with 256 as 'length' parameter
44
PASS HKDF derivation with 0 as 'length' parameter
55
PASS HKDF derivation with null as 'length' parameter
66
PASS HKDF derivation with undefined as 'length' parameter
7-
FAIL HKDF derivation with omitted as 'length' parameter assert_equals: deriveBits correctly threw OperationError: Not enough arguments expected "OperationError" but got "TypeError"
7+
PASS HKDF derivation with omitted as 'length' parameter
88
PASS PBKDF2 derivation with 256 as 'length' parameter
99
PASS PBKDF2 derivation with 0 as 'length' parameter
1010
PASS PBKDF2 derivation with null as 'length' parameter
1111
PASS PBKDF2 derivation with undefined as 'length' parameter
12-
FAIL PBKDF2 derivation with omitted as 'length' parameter assert_equals: deriveBits correctly threw OperationError: Not enough arguments expected "OperationError" but got "TypeError"
12+
PASS PBKDF2 derivation with omitted as 'length' parameter
1313
PASS ECDH derivation with 256 as 'length' parameter
1414
FAIL ECDH derivation with 0 as 'length' parameter assert_array_equals: Derived bits do not match the expected result. lengths differ, expected array object "" length 0, got object "87,31,26,232,151,28,227,35,250,17,131,137,203,95,65,196,59,61,181,161" length 32
1515
PASS ECDH derivation with null as 'length' parameter
1616
PASS ECDH derivation with undefined as 'length' parameter
17-
FAIL ECDH derivation with omitted as 'length' parameter promise_test: Unhandled rejection with value: object "TypeError: Not enough arguments"
17+
PASS ECDH derivation with omitted as 'length' parameter
1818
PASS X25519 derivation with 256 as 'length' parameter
1919
FAIL X25519 derivation with 0 as 'length' parameter assert_array_equals: Derived bits do not match the expected result. lengths differ, expected array object "" length 0, got object "63,245,136,2,149,247,97,118,8,143,137,228,61,254,190,126,161,149,0,8" length 32
2020
PASS X25519 derivation with null as 'length' parameter
2121
PASS X25519 derivation with undefined as 'length' parameter
22-
FAIL X25519 derivation with omitted as 'length' parameter promise_test: Unhandled rejection with value: object "TypeError: Not enough arguments"
22+
PASS X25519 derivation with omitted as 'length' parameter
2323

LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/derived_bits_length.https.any.worker-expected.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ PASS HKDF derivation with 256 as 'length' parameter
44
PASS HKDF derivation with 0 as 'length' parameter
55
PASS HKDF derivation with null as 'length' parameter
66
PASS HKDF derivation with undefined as 'length' parameter
7-
FAIL HKDF derivation with omitted as 'length' parameter assert_equals: deriveBits correctly threw OperationError: Not enough arguments expected "OperationError" but got "TypeError"
7+
PASS HKDF derivation with omitted as 'length' parameter
88
PASS PBKDF2 derivation with 256 as 'length' parameter
99
PASS PBKDF2 derivation with 0 as 'length' parameter
1010
PASS PBKDF2 derivation with null as 'length' parameter
1111
PASS PBKDF2 derivation with undefined as 'length' parameter
12-
FAIL PBKDF2 derivation with omitted as 'length' parameter assert_equals: deriveBits correctly threw OperationError: Not enough arguments expected "OperationError" but got "TypeError"
12+
PASS PBKDF2 derivation with omitted as 'length' parameter
1313
PASS ECDH derivation with 256 as 'length' parameter
1414
FAIL ECDH derivation with 0 as 'length' parameter assert_array_equals: Derived bits do not match the expected result. lengths differ, expected array object "" length 0, got object "87,31,26,232,151,28,227,35,250,17,131,137,203,95,65,196,59,61,181,161" length 32
1515
PASS ECDH derivation with null as 'length' parameter
1616
PASS ECDH derivation with undefined as 'length' parameter
17-
FAIL ECDH derivation with omitted as 'length' parameter promise_test: Unhandled rejection with value: object "TypeError: Not enough arguments"
17+
PASS ECDH derivation with omitted as 'length' parameter
1818
PASS X25519 derivation with 256 as 'length' parameter
1919
FAIL X25519 derivation with 0 as 'length' parameter assert_array_equals: Derived bits do not match the expected result. lengths differ, expected array object "" length 0, got object "63,245,136,2,149,247,97,118,8,143,137,228,61,254,190,126,161,149,0,8" length 32
2020
PASS X25519 derivation with null as 'length' parameter
2121
PASS X25519 derivation with undefined as 'length' parameter
22-
FAIL X25519 derivation with omitted as 'length' parameter promise_test: Unhandled rejection with value: object "TypeError: Not enough arguments"
22+
PASS X25519 derivation with omitted as 'length' parameter
2323

LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/idlharness.https.any-expected.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ PASS SubtleCrypto interface: operation verify(AlgorithmIdentifier, CryptoKey, Bu
4949
PASS SubtleCrypto interface: operation digest(AlgorithmIdentifier, BufferSource)
5050
PASS SubtleCrypto interface: operation generateKey(AlgorithmIdentifier, boolean, sequence<KeyUsage>)
5151
PASS SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)
52-
PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)
52+
PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?)
5353
PASS SubtleCrypto interface: operation importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>)
5454
PASS SubtleCrypto interface: operation exportKey(KeyFormat, CryptoKey)
5555
PASS SubtleCrypto interface: operation wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)
@@ -70,8 +70,8 @@ PASS SubtleCrypto interface: crypto.subtle must inherit property "generateKey(Al
7070
PASS SubtleCrypto interface: calling generateKey(AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
7171
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)" with the proper type
7272
PASS SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
73-
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)" with the proper type
74-
PASS SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long) on crypto.subtle with too few arguments must throw TypeError
73+
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?)" with the proper type
74+
PASS SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?) on crypto.subtle with too few arguments must throw TypeError
7575
PASS SubtleCrypto interface: crypto.subtle must inherit property "importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>)" with the proper type
7676
PASS SubtleCrypto interface: calling importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
7777
PASS SubtleCrypto interface: crypto.subtle must inherit property "exportKey(KeyFormat, CryptoKey)" with the proper type

LayoutTests/imported/w3c/web-platform-tests/WebCryptoAPI/idlharness.https.any.worker-expected.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ PASS SubtleCrypto interface: operation verify(AlgorithmIdentifier, CryptoKey, Bu
4949
PASS SubtleCrypto interface: operation digest(AlgorithmIdentifier, BufferSource)
5050
PASS SubtleCrypto interface: operation generateKey(AlgorithmIdentifier, boolean, sequence<KeyUsage>)
5151
PASS SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)
52-
PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)
52+
PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?)
5353
PASS SubtleCrypto interface: operation importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>)
5454
PASS SubtleCrypto interface: operation exportKey(KeyFormat, CryptoKey)
5555
PASS SubtleCrypto interface: operation wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)
@@ -70,8 +70,8 @@ PASS SubtleCrypto interface: crypto.subtle must inherit property "generateKey(Al
7070
PASS SubtleCrypto interface: calling generateKey(AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
7171
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)" with the proper type
7272
PASS SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
73-
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)" with the proper type
74-
PASS SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long) on crypto.subtle with too few arguments must throw TypeError
73+
PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?)" with the proper type
74+
PASS SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier, CryptoKey, optional unsigned long?) on crypto.subtle with too few arguments must throw TypeError
7575
PASS SubtleCrypto interface: crypto.subtle must inherit property "importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>)" with the proper type
7676
PASS SubtleCrypto interface: calling importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError
7777
PASS SubtleCrypto interface: crypto.subtle must inherit property "exportKey(KeyFormat, CryptoKey)" with the proper type

LayoutTests/imported/w3c/web-platform-tests/interfaces/WebCryptoAPI.idl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ interface SubtleCrypto {
6868
sequence<KeyUsage> keyUsages );
6969
Promise<ArrayBuffer> deriveBits(AlgorithmIdentifier algorithm,
7070
CryptoKey baseKey,
71-
unsigned long length);
71+
optional unsigned long? length = null);
7272

7373
Promise<CryptoKey> importKey(KeyFormat format,
7474
(BufferSource or JsonWebKey) keyData,

Source/WebCore/crypto/CryptoAlgorithm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void CryptoAlgorithm::generateKey(const CryptoAlgorithmParameters&, bool, Crypto
6060
exceptionCallback(ExceptionCode::NotSupportedError);
6161
}
6262

63-
void CryptoAlgorithm::deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&)
63+
void CryptoAlgorithm::deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, std::optional<size_t>, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&)
6464
{
6565
exceptionCallback(ExceptionCode::NotSupportedError);
6666
}

Source/WebCore/crypto/CryptoAlgorithm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class CryptoAlgorithm : public ThreadSafeRefCounted<CryptoAlgorithm> {
6868
virtual void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
6969
virtual void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
7070
virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&);
71-
virtual void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
71+
virtual void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, std::optional<size_t> length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
7272
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=169262
7373
virtual void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&, UseCryptoKit);
7474
virtual void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&, UseCryptoKit);

Source/WebCore/crypto/SubtleCrypto.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ void SubtleCrypto::deriveKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& a
936936
promise->reject(result.releaseException().code(), "Cannot get key length from derivedKeyType"_s);
937937
return;
938938
}
939-
size_t length = result.releaseReturnValue();
939+
std::optional<size_t> length = result.releaseReturnValue();
940940

941941
auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(importParams->identifier);
942942
auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);
@@ -972,7 +972,7 @@ void SubtleCrypto::deriveKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& a
972972
algorithm->deriveBits(*params, baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
973973
}
974974

975-
void SubtleCrypto::deriveBits(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, unsigned length, Ref<DeferredPromise>&& promise)
975+
void SubtleCrypto::deriveBits(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, std::optional<unsigned> length, Ref<DeferredPromise>&& promise)
976976
{
977977
auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::DeriveBits);
978978
if (paramsOrException.hasException()) {

0 commit comments

Comments
 (0)