Modified: trunk/LayoutTests/platform/gtk/TestExpectations (219534 => 219535)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2017-07-15 00:29:52 UTC (rev 219534)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2017-07-15 05:20:32 UTC (rev 219535)
@@ -767,7 +767,6 @@
webkit.org/b/133122 crypto/subtle/ec-import-pkcs8-key-export-pkcs8-key-p384.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-export-key-malformed-parameters.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-import-jwk-key-export-pkcs8-key.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/rsa-import-pkcs8-key-export-jwk-key.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-import-pkcs8-key-export-pkcs8-key.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-import-spki-key-export-spki-key.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-indexeddb-non-exportable-private.html [ Skip ]
@@ -775,12 +774,9 @@
webkit.org/b/133122 crypto/subtle/rsa-indexeddb-private.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-indexeddb.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-oaep-generate-export-key-pkcs8.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/rsa-oaep-import-pkcs8-key.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsa-pss-generate-export-key-pkcs8.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsaes-pkcs1-v1_5-generate-export-key-pkcs8.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/rsaes-pkcs1-v1_5-import-pkcs8-key.html [ Skip ]
webkit.org/b/133122 crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-pkcs8.html [ Skip ]
-webkit.org/b/133122 crypto/subtle/rsassa-pkcs1-v1_5-import-pkcs8-key.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/aes-cfb-import-key-decrypt.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/aes-cfb-import-key-encrypt.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/aes-cfb-import-key-unwrap-key.html [ Skip ]
@@ -793,7 +789,6 @@
webkit.org/b/133122 crypto/workers/subtle/multiple-postMessage-worker.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/raw-postMessage-worker.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/rsa-export-pkcs8-key.html [ Skip ]
-webkit.org/b/133122 crypto/workers/subtle/rsa-import-pkcs8-key.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/rsa-postMessage-worker.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/rsa-pss-import-key-sign.html [ Skip ]
webkit.org/b/133122 crypto/workers/subtle/rsa-pss-import-key-verify.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (219534 => 219535)
--- trunk/Source/WebCore/ChangeLog 2017-07-15 00:29:52 UTC (rev 219534)
+++ trunk/Source/WebCore/ChangeLog 2017-07-15 05:20:32 UTC (rev 219535)
@@ -1,3 +1,43 @@
+2017-07-14 Zan Dobersek <zdober...@igalia.com>
+
+ [GCrypt] Implement CryptoKeyRSA PKCS#8 imports
+ https://bugs.webkit.org/show_bug.cgi?id=173696
+
+ Reviewed by Jiewen Tan.
+
+ Implement the PKCS#8 import operation for RSA keys for platforms that use
+ libgcrypt.
+
+ In CryptoKeyRSA::importPkcs8(), the provided key data is decoded against the
+ 'PrivateKeyInfo` ASN.1 structure. We then validate the `version` element and
+ check that the `privateKeyAlgorithm.algorithm` element contains a supported
+ object identifier. This check is for now mostly superficial, only ensuring
+ that the object identifier is either id-rsaEncryption, id-RSAES-OAEP or
+ id-RSASSA-PSS. This has to be further extended to also check the
+ id-sha{1,256,384,512}WithRSAEncryption identifiers as well as decoding the
+ `privateKeyAlgorithm.parameters` element against a specific ASN.1 structure, if
+ necessary (RSASSA-PSS-params or RSAES-OAEP-params), and cross-checking the
+ specified digest algorithm with the algorithm that's specified through the main
+ object identifier or the structure contained in `privateKeyAlgorithm.parameters`.
+ This is avoided for now because no test in WebKit or the web-platform-tests
+ suite covers this detail of the specification.
+
+ Data under the `privateKey` element is decoded against the `RSAPrivateKey` ASN.1
+ structure, and the `version` element of that structure is validated. We then
+ retrieve data from that structure for the modulus, public exponent, private
+ exponent, both primes, both exponents and the coefficient parameters, bailing if
+ any of them is missing. Because libgcrypt switches the use of p and q parameters,
+ deviating from the standard use, we have to recompute the u parameter (the
+ coefficient). With that calculated, we're then able to construct the `private-key`
+ s-_expression_, embedding into it all the necessary parameters, and transferring
+ the ownership of this object to the new CryptoKeyRSA object that's then returned
+ from the importPkcs8() method.
+
+ No new tests -- related tests are now passing and are unskipped.
+
+ * crypto/gcrypt/CryptoKeyRSAGCrypt.cpp:
+ (WebCore::CryptoKeyRSA::importPkcs8):
+
2017-07-14 Chris Dumez <cdu...@apple.com>
Possible crash in ~UserGestureIndicator() when on non-main thread
Modified: trunk/Source/WebCore/crypto/gcrypt/CryptoKeyRSAGCrypt.cpp (219534 => 219535)
--- trunk/Source/WebCore/crypto/gcrypt/CryptoKeyRSAGCrypt.cpp 2017-07-15 00:29:52 UTC (rev 219534)
+++ trunk/Source/WebCore/crypto/gcrypt/CryptoKeyRSAGCrypt.cpp 2017-07-15 05:20:32 UTC (rev 219535)
@@ -321,11 +321,99 @@
return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Public, platformKey.release(), extractable, usages));
}
-RefPtr<CryptoKeyRSA> CryptoKeyRSA::importPkcs8(CryptoAlgorithmIdentifier, std::optional<CryptoAlgorithmIdentifier>, Vector<uint8_t>&&, bool, CryptoKeyUsageBitmap)
+RefPtr<CryptoKeyRSA> CryptoKeyRSA::importPkcs8(CryptoAlgorithmIdentifier identifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
- notImplemented();
+ // Decode the `PrivateKeyInfo` structure using the provided key data.
+ PAL::TASN1::Structure pkcs8;
+ if (!PAL::TASN1::decodeStructure(&pkcs8, "WebCrypto.PrivateKeyInfo", keyData))
+ return nullptr;
- return nullptr;
+ // Validate `version`.
+ {
+ auto version = PAL::TASN1::elementData(pkcs8, "version");
+ if (!version)
+ return nullptr;
+
+ if (version->size() != 1 || version->at(0) != 0x00)
+ return nullptr;
+ }
+
+ // Validate `privateKeyAlgorithm.algorithm`.
+ {
+ auto algorithm = PAL::TASN1::elementData(pkcs8, "privateKeyAlgorithm.algorithm");
+ if (!algorithm)
+ return nullptr;
+
+ if (!supportedAlgorithmIdentifier(algorithm->data(), algorithm->size()))
+ return nullptr;
+ }
+
+ // Decode the `RSAPrivateKey` structure using the `privateKey` data.
+ PAL::TASN1::Structure rsaPrivateKey;
+ {
+ auto privateKey = PAL::TASN1::elementData(pkcs8, "privateKey");
+ if (!privateKey)
+ return nullptr;
+
+ if (!PAL::TASN1::decodeStructure(&rsaPrivateKey, "WebCrypto.RSAPrivateKey", *privateKey))
+ return nullptr;
+ }
+
+ // Validate `privateKey.version`.
+ {
+ auto version = PAL::TASN1::elementData(rsaPrivateKey, "version");
+ if (!version)
+ return nullptr;
+
+ if (version->size() != 1 || version->at(0) != 0x00)
+ return nullptr;
+ }
+
+ // Retrieve the `modulus`, `publicExponent`, `privateExponent`, `prime1`, `prime2`,
+ // `exponent1`, `exponent2` and `coefficient` data and embed it into the `public-key` s-_expression_.
+ PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
+ {
+ auto modulus = PAL::TASN1::elementData(rsaPrivateKey, "modulus");
+ auto publicExponent = PAL::TASN1::elementData(rsaPrivateKey, "publicExponent");
+ auto privateExponent = PAL::TASN1::elementData(rsaPrivateKey, "privateExponent");
+ auto prime1 = PAL::TASN1::elementData(rsaPrivateKey, "prime1");
+ auto prime2 = PAL::TASN1::elementData(rsaPrivateKey, "prime2");
+ auto exponent1 = PAL::TASN1::elementData(rsaPrivateKey, "exponent1");
+ auto exponent2 = PAL::TASN1::elementData(rsaPrivateKey, "exponent2");
+ auto coefficient = PAL::TASN1::elementData(rsaPrivateKey, "coefficient");
+
+ if (!modulus || !publicExponent || !privateExponent
+ || !prime1 || !prime2 || !exponent1 || !exponent2 || !coefficient)
+ return nullptr;
+
+ // libgcrypt inverts the use of p and q parameters, so we have to recalculate the `coefficient` value.
+ PAL::GCrypt::Handle<gcry_mpi_t> uMPI(gcry_mpi_new(0));
+ {
+ PAL::GCrypt::Handle<gcry_mpi_t> pMPI;
+ gcry_error_t error = gcry_mpi_scan(&pMPI, GCRYMPI_FMT_USG, prime1->data(), prime1->size(), nullptr);
+ if (error != GPG_ERR_NO_ERROR)
+ return nullptr;
+
+ PAL::GCrypt::Handle<gcry_mpi_t> qMPI;
+ error = gcry_mpi_scan(&qMPI, GCRYMPI_FMT_USG, prime2->data(), prime2->size(), nullptr);
+ if (error != GPG_ERR_NO_ERROR)
+ return nullptr;
+
+ gcry_mpi_invm(uMPI, qMPI, pMPI);
+ }
+
+ gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %M)))",
+ modulus->size(), modulus->data(),
+ publicExponent->size(), publicExponent->data(),
+ privateExponent->size(), privateExponent->data(),
+ prime2->size(), prime2->data(), prime1->size(), prime1->data(), uMPI.handle());
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return nullptr;
+ }
+ }
+
+ return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Private, platformKey.release(), extractable, usages));
}
ExceptionOr<Vector<uint8_t>> CryptoKeyRSA::exportSpki() const