We currently use the crate `aws-lc-rs` for HKDF in the WebCrypto API.
When generating output bytes from the output of HKDF-Expand operation
(OKM, Output Key Material), it enforces the requested output length must
match the length of key type (see error condition of `Okm::fill` at
https://docs.rs/aws-lc-rs/1.14.1/aws_lc_rs/hkdf/struct.Okm.html#method.fill).
However, according to the WebCrypto API specification, user should be
allowed to choose the output length
(https://w3c.github.io/webcrypto/#hkdf-operations-derive-bits). The
restriction from `aws-lc-rs` causes several HKDF-related WPT tests to
fail.
This patch switches to use a more flexible crate `hkdf`
(https://crates.io/crates/hkdf) for implementing HKDF in our WebCrypto
API, and allowing variable length output. This helps to make those
HKDF-related WPT tests pass.
Testing: Pass some WPT tests that were expected to fail.
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This patch flattens nested match arms in `NormalizedAlgorithm` to
simplify our code. Moreover, primarily matching the algorithm names,
instead of matching the enum variant types, makes more sense, since some
algorithms share the same enum variant type.
Testing: Refactoring. Existing tests suffice.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
We parse the `parameter` field of the `algorithm` AlgorithmIdentifier
field of `spki` and `pkcs8` of ECDH keys as an object identifier.
However, according to WebCrypto API specification, we should parse it as
an `ECParameters` ASN.1 type defined in [RFC5480].
```plaintext
ECParameters ::= CHOICE {
namedCurve OBJECT IDENTIFIER
-- implicitCurve NULL
-- specifiedCurve SpecifiedECDomain
}
```
Although our current implementation works fine since `ECParameters` is
defined as a `CHOICE` type with an object identifier as the only option,
it is technically incorrect. This patch fixes this mistake.
Testing: No behavioral change. Existing tests suffice.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Finish adding ECDSA support to WebCrypto API. This patch implements sign
operation of ECDSA, using ECDSA implementation from the crates `ecdsa`
for the operation, `p256`, `p384`, `p521`, and `elliptic_curve` for the
key, and `sha1`, `sha2` and `digest` for digesting messages.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding ECDSA support to WebCrypto API. This patch implements
verify operation of ECDSA, using ECDSA implementation from the crates
`ecdsa` for the operation, `p256`, `p384`, `p521`, and `elliptic_curve`
for the key, and `sha1`, `sha2` and `digest` for digesting messages.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding ECDSA support to WebCrypto API. This patch implements
generate key operation of ECDSA, using ECDSA implementation from the
crates `p256`, `p384`, `p521` and `elliptic_curve`.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding ECDSA support to WebCrypto API. This patch implements
export key operation of ECDSA, using ECDSA implementation from the
crates `p256`, `p384`, `p521` and `elliptic_curve`.
Testing:
- Pass some WPT tests that were expected to fail.
- The new FAIL expectations are added to
`wrapKey_unwrapKey.https.any.js.ini`, which require the
not-yet-implemented sign/verify operations of ECDSA and RSA-OAEP. These
tests were skipped by WPT when the export key operation of ECDSA had not
been implemented at the time.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Start adding ECDSA support to WebCrypto API. This patch implements
import key operation of ECDSA, using ECDSA implementation from the
crates `p256`, `p384`, `p521` and `elliptic_curve`.
Testing:
- Pass some WPT tests that were expected to fail.
- Remaining failed tests in `ec_importKey.https.any.js.ini` require the
not-yet-implemented export key operation of ECDSA.
- The new FAIL expectations are added to `ecdsa.https.any.js.ini`, which
require the not-yet-implemented sign/verify operations of ECDSA. These
tests were skipped by WPT because the import key operation had not been
implemented at the time.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Finish adding X25519 support to WebCrypto API. This patch implements
derive bits operation of X25519, using X25519 implementation from the
crate `x25519-dalek`.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding X25519 support to WebCrypto API. This patch
implements generate key operation of X25519, using X25519 implementation
from the crate `x25519-dalek`.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding X25519 support to WebCrypto API. This patch
implements export key operation of X25519, using X25519 implementation
from the crate `x25519-dalek`.
Testing:
- Pass some WPT tests that were expected to fail.
- Some FAIL expectations are added. They require derive_bits operations
of X25519, and RSA-OAEP, which have not yet implemented.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Finish adding ECDH support to WebCrypto API. This patch implements
derive bits operation of ECDH.
Testing: Pass some WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Start adding X25519 support to WebCrypto API. This patch implements
import key operation of X25519, using X25519 implementation from the
crate `x25519-dalek`.
Testing:
- Pass some WPT tests that were expected to fail.
- Some FAIL expectations are added. They require other
not-yet-implemented operations of X25519. WPT skipped them when "import
key" operation for X25519 were not yet implemented.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
The `SubtleCrypto` interface of WebCrypto API needs to encode and decode
keys in base64 alphabets when exporting/importing keys in JsonWebKey
format.
We currently use the `base64` crate to handle base64 encoding and
decoding. This patch switches to use the `base64ct` crate, which is a
constant-time implementation of base64 alphabets.
Using constant-time implementation to handle base64 encoding and
decoding of cryptographic secret provides a better protection against
time-based sidechannel attack.
Remarks: The multi-line changes in `ecdh_operation.rs` are mostly caused
by `./mach fmt`.
Testing: Refactoring. Existing tests suffice.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding ECDH support to WebCrypto API. This patch implements
generate key operation of ECDH.
Testing:
- Pass some WPT tests that were expected to fail.
- Some FAIL expectations are added. They require not-yet-implemented
"derive bits" operation of ECDH. WPT skipped them when "generate key"
operation for ECDH were not yet implemented.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Continue on adding ECDH support to WebCrypto WPI. This patch implements
export key operation of ECDH.
Testing:
- Pass some WPT tests that were expected to fail.
- Some FAIL expectations are added. They require not-yet-implemented
"derive bits" operation of ECDH. WPT skipped them when "export key"
operation for ECDH were not yet implemented.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
These two functions no longer use unsafe code. The annotation
`#[allow(unsafe_code)]` can be removed.
Testing: Refactoring. Existing tests suffice.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Implement import key operation for ECDH, using cryptographic calculation
implementation from the crates `p256`, `p384` and `p521`.
Testing:
- Pass some WPT tests that were expected to fail.
- Some FAIL expectations are added. They are related to the
not-yet-implemented "derive bits" operation of ECDH. WPT skipped them
when "import key" operation for ECDH were not yet implemented.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This patch adds the cryptographic algorithm Ed25519 support to
`SubtleCrypto` interface, covering the "sign", "verify", "generateKey",
"importKey" and "exportKey" operations.
One may notice that the following related WPT tests do not pass in this
patch. They are caused by the unimplemented Step 2 and 3 of the "verify"
operation (https://w3c.github.io/webcrypto/#ed25519-operations-verify)
of Ed25519, which check whether the key represents an invalid point or a
small-order element on the Elliptic Curve of Ed25519.
```plaintext
[Ed25519 Verification checks with small-order key of order - Test 0]
[Ed25519 Verification checks with small-order key of order - Test 1]
[Ed25519 Verification checks with small-order key of order - Test 2]
[Ed25519 Verification checks with small-order key of order - Test 12]
[Ed25519 Verification checks with small-order key of order - Test 13]
```
The specification mentions that not all implementation perform this
check. There is also a discussion on it at specification level
(https://github.com/WICG/webcrypto-secure-curves/issues/27). As of
today, Chrome, Edge, Firefox and Safari do not implement it, and do not
pass those tests [1]. Meanwhile, the `aws-lc-rs` crate does not provide
relevant code. We may leave it unimplemented for now, and decide what to
do later.
[1]
https://wpt.fyi/results/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.html?run_id=4820942170882048&run_id=6289205228732416&run_id=5178672043786240&run_id=5113794717286400
Testing: Pass WPT tests that were expected to fail.
Fixes: Part of #39060
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This wrapper was added in order to eliminate the number of file
descriptors used accessing `/dev/urandom`, but these days `osrandom` and
by proxy `rand` will try to use `getrandom` on Linux and similar system
APIs on other platforms [^1].
This is a trial balloon for removing the wrapper, since almost all
modern Linux systems have `getrandom` (available since Linux
3.17).
[^1]: https://docs.rs/getrandom/0.3.4/getrandom/#supported-targets
Testing: Should not change observable behavior (only in random ways), so
should
be covered by WPT tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
After the PR #39814 being merged, we can access the `[[algorithm]]`
internal slot of a `CryptoKey` directly in Rust, without doing a JS
object conversion.
This patch leverages this feature to simplify HMAC operation steps that
access the `[[algorithm]]` internal slot of `CryptoKey`.
Testing: Refactoring. Existing WPT tests suffice.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
The WebCrypto API specification was updated
(https://github.com/w3c/webcrypto/pull/380) to allow zero length in
deriveBits operation of HKDF and PBKDF2. This patch updates our
implementation accordingly.
Testing: Pass some WPT tests that were expected to fail.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
CryptoKey interface has an internal slot named [[algorithm]], which
store a WebIDL dictionary [1]. CryptoKey also stores a cached ECMAScript
Object associated with the [[algorithm]] internal slot, and returns this
object when the interface member `algorithm` is called [2].
In our current implementation, when we create a new `CryptoKey`, we need
to manually construct an ECMAScript Object for the [[algorithm]]
internal slot, and provide it to `CryptoKey::new`. Then, the provided
object directly is stored in `CryptoKey`.
There are several issues with this design.
- `CryptoKey::new` accepts arbitrary ECMAScript Object via a
`HandleObject` value. It basically relies on the caller to provide a
correct object.
- When we want to access the dictionary members of the [[algorithm]]
internal slot, we need to first convert the ECMAScript Object back to a
WebIDL dictionary. Although we have a separate field in the `CryptoKey`
struct to store the `name` member of the dictionary for convenience, it
is still not easy to access other members.
This patch makes the following change: Instead of storing an ECMAScript
Object provided by the caller and a separate name for convenience, we
store (our "subtle" struct of) WebIDL dictionary type in Rust, generated
by codegen, in the [[algorithm]] internal slot. Moreover, the cached
ECMAScript Object associated with the [[algorithm]] internal slot is
constructed from the [[algorithm]] internal slot internally, and we
store it in the [[algorithm_cached]] internal slot.
The benefits of this new design are:
- The caller can directly provide the WebIDL dictionary in Rust to
`CryptoKey`, without manually creating an ECMAScript Object.
- When we want to access the [[algorithm]] internal slot, we don't need
to do a ECMAScript-Object-to-dictionary conversion.
- The Rust type system with an implementation of the
`SafeToJSValConversion` trait can guarantee the cached ECMAScript Object
associated with the [[algorithm]] internal slot is in good shape.
[1] https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-algorithm
[2] https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm
Testing: Refatoring. No behavioral change. Existing WPT test suffices.
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here. This patch is the last piece of this
migration.
In this patch:
- The `SubtleCrypto.deriveKey` and `SubtleCrypto.deriveBits` method are
migrated from using existing `normalize_algorithm_for_derive_bits`,
`normalize_algorithm_for_import_key` and
`normalize_algorithm_for_get_key_length` functions to using the new
`normalize_algorithm` function.
- The custom types `DeriveBitsAlgorithm`, `ImportKeyAlgorithm` and
`GetKeyLengthAlgorithm` used by `normalize_algorithm_for_derive_bits`,
`normalize_algorithm_for_import_key` and
`normalize_algorithm_for_get_key_length` are removed.
- The custom type `DigestAlgorithm` is also removed.
- The `SubtleHkdfParams::derive_bits` function is moved to sub-module
`hkdf_operation`.
- The `Subtlepkdf2Params::derive_bits` function is moved to sub-module
`pbkdf2_operation`.
- The `SubtleHmacImportParams::get_key_length` function is moved to
sub-module `hmac_operation`.
- The `get_key_length_for_aes` function is moved to sub-module
`aes_operation`.
- The `import_key_aes`, `import_key_hkdf`, `import_key_hmac` and
`import_key_pbkdf2` are removed since they are no longer in use.
Testing: Refactoring. Existing WPT tests suffice.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here.
In this patch:
- The `SubtleCrypto.wrapKey` and `SubtleCrypto.unwrapKey` method is
migrated from using existing `normalize_algorithm_for_key_wrap` function
to using the new `normalize_algorithm` function.
- `SubtleCrypto::wrap_key_aes_kw` and `SubtleCrypto::unwrap_key_aes_kw`
are moved to the sub-module `aes_operation`.
- The custom type `KeyWrapAlgorithm` used by
`normalize_algorithm_for_key_wrap` is also removed.
- The following algorithm that had been copied to `aes_operation`
sub-module are removed in this patch since they are no longer used.
- `SubtleCrypto::encrypt_decrypt_aes_ctr`
- `SubtleCrypto::encrypt_aes_gcm`
- `SubtleCrypto::decrypt_aes_gcm`
- `SubtleCrypto::export_aes_aes`
Testing: Refactoring. Existing WPT tests suffice.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here.
In this patch:
- The `SubtleCrypto.importKey` method is migrated from using existing
`normalize_algorithm_for_import_key` function to using the new
`normalize_algorithm` function.
- The `import_key_aes`, `import_key_hkdf`, `import_key_hmac` and
`import_key_pbkdf2` are copied to the `aes_operation`, `hkdf_operation`,
`hmac_operation`, `pbkdf2_operation` submodules, according to their
types of cryptographic algorithms.
- The above `import_key_xxx` methods are supposed to move the
submodules, but they are copied without removal in this patch. It is
because they are used by the `wrapKey` and `unwrapKey` operations which
have not migrated at this moment. Once `wrapKey` and `unwrapKey` are
migrated, they can be removed.
- The custom type `ImportKeyAlgorithm` and
`normalize_algorithm_for_import_key` are supposed to be removed, but
they are not removed at this moment since they are used by the `wrapKey`
and `unwrapKey` operations which have not migrated. Once `wrapKey` and
`unwrapKey` are migrated, they can be removed.
Remarks: According to the spec, the `SubtleCrypto.exportKey` method does
not use the algorithm normalization. However, we move the "export"
counterpart of the above `import_key_xxx` functions all together. So,
some refactoring is also made to the `ExportKey` method.
Testing: Refactoring. Existing WPT tests suffice.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here.
In this patch:
- The `SubtleCrypto.generateKey` method is migrated from using existing
`normalize_algorithm_for_generate_key` function to using the new
`normalize_algorithm` function.
- The custom type `KeyGenerationAlgorithm` used by
`normalize_algorithm_for_generate_key` is removed.
- The functions `generate_key_aes` and `generate_key_hmac` are moved to
the sub-module `aes_operation` and `hmac_operation`, respectively.
Testing: Refactoring. Existing WPT tests suffice.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This implements LazyDOMString (from now on DOMString) as outlined in
https://github.com/servo/servo/issues/39479.
Constructing from a *mut JSString we keep the in a
RootedTraceableBox<Heap<*mut JSString>> and transform
the string into a rust string if necessary via the `make_rust_string`
method.
Methods used in script are implemented on this string. Currently we
transform the string at all times.
But in the future more efficient implementations are possible.
We implement the safety critical sections in a separate module
DOMStringInner which allows simple constructors, `make_rust_string` and
the `bytes` method.
This method returns the new type `EncodedBytes` which contains the
reference to the underlying string in either format.
Testing: WPT tests still seem to work, so this should test this
functionality.
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here.
This patch migrates the `encrypt` and `decrypt` operation from using
existing `normalize_algorithm_for_encrypt_or_decrypt` function to using
the new `normalize_algorithm` function.
The functions
- `SubtleCrypto::encrypt_aes_cbc`,
- `SubtleCrypto::decrypt_aes_cbc`,
- `SubtleCrypto::encrypt_decrypt_aes_ctr`,
- `SubtleCrypto::encrypt_aes_gcm` and
- `SubtleCrypto::decrypt_aes_gcm`
should be moved to the sub-module `aes_operation`, but, they are only
copied to the sub-module without being removed. This is because the
`wrapKey` and `unwrapKey` operation (not yet migrated) depend on them.
When the two operations are also migrated, we can remove them.
Testing: Refactoring. Existing WPT tests are enough.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
Refactoring of the algorithm normalization in #39431 introduces a new
algorithm normalization procedure to replace the existing one, and we
continue the migration here.
In this patch:
- The `sign` and `verify` operation is migrated from using existing
`normalize_algorithm_for_sign_or_verify` function to using the new
`normalize_algorithm` function.
- The custom type `SignatureAlgorithm` used by
`normalize_algorithm_for_sign_or_verify` is removed.
- The functions `sign_hmac` and `verify_hmac` are moved to the
sub-module `hmac_operation`.
Testing: Refactoring. Existing WPT tests suffice.
Fixes: Part of #39368
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
In our current implementation, we have multiple functions such as
`normalize_algoirthm_for_encrypt_or_decrypt` and
`normalize_algorithm_for_sign_or_verify` to normalize an algorithm, and
each of them works slightly differently. However, the spec defines a
single normalization procedure to handle all normalization.
This patch tries to consolidate our functions into a single
spec-compliant normalization function named `normalize_algorithm`.
The refactoring involves many existing code, so this patch only
introduces the new infrastructure without touching the existing. When
this patch gets approved and merged, we can then start migrating the
existing to the new infrastructure. (Note that SHA's digestion and
AES_CTR's encryption are also copied to the new infrastructure as
demonstration.)
More details about the refactoring can be found in the comment:
https://github.com/servo/servo/issues/39368#issuecomment-3316943206
Testing: The new code is not in used right now. No test is needed.
Fixes: Part of #39368
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>