tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b8764182bedeeb78f0f23c009544a49ab071282f
parent 415ea8686f4ad0422d2b0f2b17482750eaa3dcd3
Author: Anna <anna.weine@mozilla.com>
Date:   Mon, 27 Oct 2025 17:13:56 +0000

Bug 1971499 - WebCrypto support for compressed points r=jschanck

Differential Revision: https://phabricator.services.mozilla.com/D266695

Diffstat:
Mdom/crypto/CryptoKey.cpp | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Dtesting/web-platform/meta/WebCryptoAPI/import_export/ec_importKey.https.any.js.ini | 290-------------------------------------------------------------------------------
2 files changed, 77 insertions(+), 308 deletions(-)

diff --git a/dom/crypto/CryptoKey.cpp b/dom/crypto/CryptoKey.cpp @@ -1266,18 +1266,8 @@ nsresult CryptoKey::PublicKeyToJwk(SECKEYPublicKey* aPubKey, } } -UniqueSECKEYPublicKey CryptoKey::PublicECKeyFromRaw( - CryptoBuffer& aKeyData, const nsString& aNamedCurve) { - UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - if (!arena) { - return nullptr; - } - - SECItem rawItem = {siBuffer, nullptr, 0}; - if (!aKeyData.ToSECItem(arena.get(), &rawItem)) { - return nullptr; - } - +bool PublicKeyHasCorrectLengthAndEncoding(const nsString& aNamedCurve, + const SECItem* key) { uint32_t flen; if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) { flen = 32; // bytes @@ -1286,17 +1276,37 @@ UniqueSECKEYPublicKey CryptoKey::PublicECKeyFromRaw( } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) { flen = 66; // bytes } else { + return false; + } + + // Here we have 2 possible inputs, either we've received an uncompressed point + // then the length is 1 + flen (x) + flen (y) and the 0th byte is + // EC_POINT_FORM_UNCOMPRESSED or we work with the compressed point then the + // length is 1 + flen (x) and the 0th byte is either + // EC_POINT_FORM_COMPRESSED_Y0 or EC_POINT_FORM_COMPRESSED_Y1 + + bool correctUncompressed = (key->len == 2 * flen + 1) && + (key->data[0] == EC_POINT_FORM_UNCOMPRESSED); + bool correctCompressed = (key->len == flen + 1) && + ((key->data[0] == EC_POINT_FORM_COMPRESSED_Y0) || + (key->data[0] == EC_POINT_FORM_COMPRESSED_Y1)); + + return correctCompressed || correctUncompressed; +} + +UniqueSECKEYPublicKey CryptoKey::PublicECKeyFromRaw( + CryptoBuffer& aKeyData, const nsString& aNamedCurve) { + UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + if (!arena) { return nullptr; } - // Check length of uncompressed point coordinates. There are 2 field elements - // and a leading point form octet (which must EC_POINT_FORM_UNCOMPRESSED). - if (rawItem.len != (2 * flen + 1)) { + SECItem rawItem = {siBuffer, nullptr, 0}; + if (!aKeyData.ToSECItem(arena.get(), &rawItem)) { return nullptr; } - // No support for compressed points. - if (rawItem.data[0] != EC_POINT_FORM_UNCOMPRESSED) { + if (!PublicKeyHasCorrectLengthAndEncoding(aNamedCurve, &rawItem)) { return nullptr; } @@ -1339,6 +1349,24 @@ UniqueSECKEYPublicKey CryptoKey::PublicOKPKeyFromRaw( return CreateECPublicKey(&rawItem, aNamedCurve); } +bool PublicECKeyEncoded(SECKEYPublicKey* aPubKey) { + if (!aPubKey) { + return false; + } + + SECItem* publicValue = &aPubKey->u.ec.publicValue; + if (!publicValue || !publicValue->data || publicValue->len == 0) { + return false; + } + + if (publicValue->data[0] == EC_POINT_FORM_COMPRESSED_Y0 || + publicValue->data[0] == EC_POINT_FORM_COMPRESSED_Y1) { + return true; + } + + return false; +} + bool CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey) { UniquePK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { @@ -1349,7 +1377,38 @@ bool CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey) { // it is imported into a PKCS#11 module, and returns CK_INVALID_HANDLE // if it is invalid. CK_OBJECT_HANDLE id = PK11_ImportPublicKey(slot.get(), aPubKey, PR_FALSE); - return id != CK_INVALID_HANDLE; + if (id == CK_INVALID_HANDLE) { + return false; + } + + // It is possible that the public key was in the decompressed form + // Thus we need to read the attribute to retrieve the key + if (aPubKey->keyType == ecKey && PublicECKeyEncoded(aPubKey)) { + ScopedAutoSECItem encodedPublicKey; + // Independently from whether the key was decompressed or not, + // the raw attribute is stored encoded. + SECStatus rv = PK11_ReadRawAttribute(PK11_TypePubKey, aPubKey, CKA_EC_POINT, + &encodedPublicKey); + if (NS_WARN_IF(rv != SECSuccess)) { + return false; + } + + SECItem decoded; + rv = SEC_QuickDERDecodeItem(aPubKey->arena, &decoded, + SEC_ASN1_GET(SEC_OctetStringTemplate), + &encodedPublicKey); + if (NS_WARN_IF(rv != SECSuccess)) { + return false; + } + + // Updating the public key + rv = SECITEM_CopyItem(aPubKey->arena, &aPubKey->u.ec.publicValue, &decoded); + if (NS_WARN_IF(rv != SECSuccess)) { + return false; + } + } + + return true; } bool CryptoKey::WriteStructuredClone(JSContext* aCX, diff --git a/testing/web-platform/meta/WebCryptoAPI/import_export/ec_importKey.https.any.js.ini b/testing/web-platform/meta/WebCryptoAPI/import_export/ec_importKey.https.any.js.ini @@ -1,290 +0,0 @@ -[ec_importKey.https.any.html] - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - -[ec_importKey.https.any.worker.html] - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDH, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDH, namedCurve: P-256}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDH, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDH, namedCurve: P-384}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, false, [\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-256 bits (raw, buffer(33, compressed), {name: ECDSA, namedCurve: P-256}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (spki, buffer(72, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-384 bits (raw, buffer(49, compressed), {name: ECDSA, namedCurve: P-384}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify, verify\])] - expected: PRECONDITION_FAILED - - [Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify, verify\])] - expected: PRECONDITION_FAILED