From 11dd5a0ae73b4d3612de6422893a25232f930b84 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Mon, 5 Jun 2023 14:52:02 +0200 Subject: [PATCH] fix(ext/crypto): fix JWK import of Ed25519 (#19279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: #18049 --------- Co-authored-by: Bartek IwaƄczuk --- ext/crypto/00_crypto.js | 14 ++++++- ext/crypto/lib.rs | 9 +++-- tools/wpt/expectation.json | 80 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 19e669acd0..d88aef219d 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -2319,7 +2319,12 @@ function importKeyEd25519( // 9. if (jwk.d !== undefined) { // https://www.rfc-editor.org/rfc/rfc8037#section-2 - const privateKeyData = ops.op_crypto_base64url_decode(jwk.d); + let privateKeyData; + try { + privateKeyData = ops.op_crypto_base64url_decode(jwk.d); + } catch (_) { + throw new DOMException("invalid private key data", "DataError"); + } const handle = {}; WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData); @@ -2337,7 +2342,12 @@ function importKeyEd25519( ); } else { // https://www.rfc-editor.org/rfc/rfc8037#section-2 - const publicKeyData = ops.op_crypto_base64url_decode(jwk.x); + let publicKeyData; + try { + publicKeyData = ops.op_crypto_base64url_decode(jwk.x); + } catch (_) { + throw new DOMException("invalid public key data", "DataError"); + } const handle = {}; WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData); diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs index 05349bf680..dc5faf5e7e 100644 --- a/ext/crypto/lib.rs +++ b/ext/crypto/lib.rs @@ -116,10 +116,11 @@ deno_core::extension!(deno_crypto, ); #[op] -pub fn op_crypto_base64url_decode(data: String) -> ZeroCopyBuf { - let data: Vec = - base64::decode_config(data, base64::URL_SAFE_NO_PAD).unwrap(); - data.into() +pub fn op_crypto_base64url_decode( + data: String, +) -> Result { + let data: Vec = base64::decode_config(data, base64::URL_SAFE_NO_PAD)?; + Ok(data.into()) } #[op] diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index 57b8ba75ab..ed29c43e4c 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -1159,12 +1159,84 @@ "Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])", "Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])" ], - "okp_importKey_failures_Ed25519.https.any.html": false, - "okp_importKey_failures_Ed25519.https.any.worker.html": false, + "okp_importKey_failures_Ed25519.https.any.html": [ + "Bad key length: importKey(raw, {name: Ed25519}, true, [verify])", + "Bad key length: importKey(raw, {name: Ed25519}, false, [verify])", + "Bad key length: importKey(raw, {name: Ed25519}, true, [verify, verify])", + "Bad key length: importKey(raw, {name: Ed25519}, false, [verify, verify])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, true, [sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, false, [sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, true, [sign, sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, false, [sign, sign])", + "Invalid key pair: importKey(jwk(private), {name: Ed25519}, true, [sign])", + "Invalid key pair: importKey(jwk(private), {name: Ed25519}, true, [sign, sign])" + ], + "okp_importKey_failures_Ed25519.https.any.worker.html": [ + "Bad key length: importKey(raw, {name: Ed25519}, true, [verify])", + "Bad key length: importKey(raw, {name: Ed25519}, false, [verify])", + "Bad key length: importKey(raw, {name: Ed25519}, true, [verify, verify])", + "Bad key length: importKey(raw, {name: Ed25519}, false, [verify, verify])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, true, [sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, false, [sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, true, [sign, sign])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: Ed25519}, false, [sign, sign])", + "Invalid key pair: importKey(jwk(private), {name: Ed25519}, true, [sign])", + "Invalid key pair: importKey(jwk(private), {name: Ed25519}, true, [sign, sign])" + ], "okp_importKey_failures_Ed448.https.any.html": false, "okp_importKey_failures_Ed448.https.any.worker.html": false, - "okp_importKey_failures_X25519.https.any.html": false, - "okp_importKey_failures_X25519.https.any.worker.html": false, + "okp_importKey_failures_X25519.https.any.html": [ + "Bad key length: importKey(raw, {name: X25519}, true, [])", + "Bad key length: importKey(raw, {name: X25519}, false, [])", + "Bad key length: importKey(jwk (public) , {name: X25519}, true, [])", + "Bad key length: importKey(jwk (public) , {name: X25519}, false, [])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" + ], + "okp_importKey_failures_X25519.https.any.worker.html": [ + "Bad key length: importKey(raw, {name: X25519}, true, [])", + "Bad key length: importKey(raw, {name: X25519}, false, [])", + "Bad key length: importKey(jwk (public) , {name: X25519}, true, [])", + "Bad key length: importKey(jwk (public) , {name: X25519}, false, [])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveBits, deriveKey])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Bad key length: importKey(jwk(private), {name: X25519}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveBits, deriveKey])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Missing JWK 'x' parameter: importKey(jwk(private), {name: X25519}, false, [deriveKey, deriveBits, deriveKey, deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits, deriveKey])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits])", + "Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])" + ], "okp_importKey_failures_X448.https.any.html": false, "okp_importKey_failures_X448.https.any.worker.html": false },