crypto/subtle/hmac-import-raw-key-export-jwk-key.html [ Pass ]
crypto/subtle/hmac-import-raw-key-export-raw-key.html [ Pass ]
crypto/subtle/hmac-import-raw-key.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-jwk-sha1.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-jwk-sha224.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-jwk-sha256.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-jwk-sha384.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-export-key-jwk-sha512.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-key.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-key-sign-verify.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-generate-key-with-leading-zeroes-in-exponent.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-private-key.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-empty-usages.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-sha1.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-sha224.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-sha256.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-sha384.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-jwk-public-key-sha512.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-sign-sha1.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-sign-sha224.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-sign-sha256.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-sign-sha384.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-sign-sha512.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-verify-sha1.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-verify-sha224.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-verify-sha256.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-verify-sha384.html [ Pass ]
+crypto/subtle/rsassa-pkcs1-v1_5-import-key-verify-sha512.html [ Pass ]
crypto/subtle/import-key-malformed-parameters.html [ Pass ]
crypto/subtle/pbkdf2-derive-bits-malformed-parametrs.html [ Pass ]
crypto/subtle/pbkdf2-import-key-derive-bits.html [ Pass ]
+2017-05-30 Zan Dobersek <zdobersek@igalia.com>
+
+ [GCrypt] RSASSA-PKCS1-v1_5 support
+ https://bugs.webkit.org/show_bug.cgi?id=171220
+
+ Reviewed by Michael Catanzaro.
+
+ Add RSASSA-PKSC1-V_15 support for configurations that use libgcrypt.
+
+ The signing operation first digests data with the specified hash algorithm.
+ That's then embedded in the data s-expression. That's then passed to the
+ gcry_pk_sign() call together with the specified key, returning a sig-val
+ s-expression containing the signature. The signature data is then retrieved
+ from the relevant MPI and returned to the caller.
+
+ The verification operation first digests data with the specified hash
+ algorithm. That's then embedded in the data s-expression. A sig-val
+ s-expression is constructed, embedding the signature data. The data and
+ sig-val s-expressions are passed to the gcry_sexp_verify() call which returns
+ the resulting error code. The verification succeeds if the returned value is
+ GPG_ERR_NO_ERROR, fails if it's GPG_ERR_BAD_SIGNATURE, or errors out with an
+ OperationError otherwise.
+
+ No new tests -- the revelant tests are passing and are unskipped, apart from
+ the ones using PKCS#8 and SPKI formats.
+
+ * crypto/gcrypt/CryptoAlgorithmRSASSA_PKCS1_v1_5GCrypt.cpp:
+ (WebCore::hashCryptoDigestAlgorithm):
+ (WebCore::hashAlgorithmName):
+ (WebCore::mpiData):
+ (WebCore::gcryptSign):
+ (WebCore::gcryptVerify):
+ (WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::platformSign):
+ (WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::platformVerify):
+
2017-05-29 Emilio Cobos Álvarez <ecobos@igalia.com>
Use the parent box style to adjust RenderStyle for alignment.
#include "CryptoKeyRSA.h"
#include "ExceptionCode.h"
#include "NotImplemented.h"
+#include "ScriptExecutionContext.h"
+#include <pal/crypto/CryptoDigest.h>
+#include <pal/crypto/gcrypt/Handle.h>
+#include <pal/crypto/gcrypt/Utilities.h>
namespace WebCore {
-void CryptoAlgorithmRSASSA_PKCS1_v1_5::platformSign(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&)
+static std::optional<PAL::CryptoDigest::Algorithm> hashCryptoDigestAlgorithm(CryptoAlgorithmIdentifier identifier)
{
- notImplemented();
+ switch (identifier) {
+ case CryptoAlgorithmIdentifier::SHA_1:
+ return PAL::CryptoDigest::Algorithm::SHA_1;
+ case CryptoAlgorithmIdentifier::SHA_224:
+ return PAL::CryptoDigest::Algorithm::SHA_224;
+ case CryptoAlgorithmIdentifier::SHA_256:
+ return PAL::CryptoDigest::Algorithm::SHA_256;
+ case CryptoAlgorithmIdentifier::SHA_384:
+ return PAL::CryptoDigest::Algorithm::SHA_384;
+ case CryptoAlgorithmIdentifier::SHA_512:
+ return PAL::CryptoDigest::Algorithm::SHA_512;
+ default:
+ return std::nullopt;
+ }
}
-void CryptoAlgorithmRSASSA_PKCS1_v1_5::platformVerify(Ref<CryptoKey>&&, Vector<uint8_t>&&, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&)
+static std::optional<const char*> hashAlgorithmName(CryptoAlgorithmIdentifier identifier)
{
- notImplemented();
+ switch (identifier) {
+ case CryptoAlgorithmIdentifier::SHA_1:
+ return "sha1";
+ case CryptoAlgorithmIdentifier::SHA_224:
+ return "sha224";
+ case CryptoAlgorithmIdentifier::SHA_256:
+ return "sha256";
+ case CryptoAlgorithmIdentifier::SHA_384:
+ return "sha384";
+ case CryptoAlgorithmIdentifier::SHA_512:
+ return "sha512";
+ default:
+ return std::nullopt;
+ }
+}
+
+static std::optional<Vector<uint8_t>> mpiData(gcry_sexp_t paramSexp)
+{
+ // Retrieve the MPI value stored in the s-expression: (name mpi-data)
+ PAL::GCrypt::Handle<gcry_mpi_t> paramMPI(gcry_sexp_nth_mpi(paramSexp, 1, GCRYMPI_FMT_USG));
+ if (!paramMPI)
+ return std::nullopt;
+
+ // Query the data length first to properly prepare the buffer.
+ size_t dataLength = 0;
+ gcry_error_t error = gcry_mpi_print(GCRYMPI_FMT_USG, nullptr, 0, &dataLength, paramMPI);
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+
+ // Finally, copy the MPI data into a properly-sized buffer.
+ Vector<uint8_t> output(dataLength);
+ error = gcry_mpi_print(GCRYMPI_FMT_USG, output.data(), output.size(), nullptr, paramMPI);
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+
+ return output;
+}
+
+static std::optional<Vector<uint8_t>> gcryptSign(gcry_sexp_t keySexp, const Vector<uint8_t>& data, CryptoAlgorithmIdentifier hashAlgorithmIdentifier)
+{
+ // Perform digest operation with the specified algorithm on the given data.
+ Vector<uint8_t> dataHash;
+ {
+ auto digestAlgorithm = hashCryptoDigestAlgorithm(hashAlgorithmIdentifier);
+ if (!digestAlgorithm)
+ return std::nullopt;
+
+ auto digest = PAL::CryptoDigest::create(*digestAlgorithm);
+ if (!digest)
+ return std::nullopt;
+
+ digest->addBytes(data.data(), data.size());
+ dataHash = digest->computeHash();
+ }
+
+ // Construct the data s-expression that contains PKCS#1-padded hashed data.
+ PAL::GCrypt::Handle<gcry_sexp_t> dataSexp;
+ {
+ auto shaAlgorithm = hashAlgorithmName(hashAlgorithmIdentifier);
+ if (!shaAlgorithm)
+ return std::nullopt;
+
+ gcry_error_t error = gcry_sexp_build(&dataSexp, nullptr, "(data(flags pkcs1)(hash %s %b))",
+ *shaAlgorithm, dataHash.size(), dataHash.data());
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+ }
+
+ // Perform the PK signing, retrieving a sig-val s-expression of the following form:
+ // (sig-val
+ // (rsa
+ // (s s-mpi)))
+ PAL::GCrypt::Handle<gcry_sexp_t> signatureSexp;
+ gcry_error_t error = gcry_pk_sign(&signatureSexp, dataSexp, keySexp);
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+
+ // Return MPI data of the embedded s integer.
+ PAL::GCrypt::Handle<gcry_sexp_t> sSexp(gcry_sexp_find_token(signatureSexp, "s", 0));
+ if (!sSexp)
+ return std::nullopt;
+
+ return mpiData(sSexp);
+}
+
+static std::optional<bool> gcryptVerify(gcry_sexp_t keySexp, const Vector<uint8_t>& signature, const Vector<uint8_t>& data, CryptoAlgorithmIdentifier hashAlgorithmIdentifier)
+{
+ // Perform digest operation with the specified algorithm on the given data.
+ Vector<uint8_t> dataHash;
+ {
+ auto digestAlgorithm = hashCryptoDigestAlgorithm(hashAlgorithmIdentifier);
+ if (!digestAlgorithm)
+ return std::nullopt;
+
+ auto digest = PAL::CryptoDigest::create(*digestAlgorithm);
+ if (!digest)
+ return std::nullopt;
+
+ digest->addBytes(data.data(), data.size());
+ dataHash = digest->computeHash();
+ }
+
+ // Construct the sig-val s-expression that contains the signature data.
+ PAL::GCrypt::Handle<gcry_sexp_t> signatureSexp;
+ gcry_error_t error = gcry_sexp_build(&signatureSexp, nullptr, "(sig-val(rsa(s %b)))",
+ signature.size(), signature.data());
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+
+ // Construct the data s-expression that contains PKCS#1-padded hashed data.
+ PAL::GCrypt::Handle<gcry_sexp_t> dataSexp;
+ {
+ auto shaAlgorithm = hashAlgorithmName(hashAlgorithmIdentifier);
+ if (!shaAlgorithm)
+ return std::nullopt;
+
+ error = gcry_sexp_build(&dataSexp, nullptr, "(data(flags pkcs1)(hash %s %b))",
+ *shaAlgorithm, dataHash.size(), dataHash.data());
+ if (error != GPG_ERR_NO_ERROR) {
+ PAL::GCrypt::logError(error);
+ return std::nullopt;
+ }
+ }
+
+ // Perform the PK verification. We report success if there's no error returned, or
+ // a failure in any other case. OperationError should not be returned at this point.
+ error = gcry_pk_verify(signatureSexp, dataSexp, keySexp);
+ return { error == GPG_ERR_NO_ERROR };
+}
+
+void CryptoAlgorithmRSASSA_PKCS1_v1_5::platformSign(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
+{
+ context.ref();
+ workQueue.dispatch(
+ [key = WTFMove(key), data = WTFMove(data), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable {
+ auto& rsaKey = downcast<CryptoKeyRSA>(key.get());
+
+ auto output = gcryptSign(rsaKey.platformKey(), data, rsaKey.hashAlgorithmIdentifier());
+ if (!output) {
+ // We should only dereference callbacks after being back to the Document/Worker threads.
+ context.postTask(
+ [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) {
+ exceptionCallback(OperationError);
+ context.deref();
+ });
+ return;
+ }
+
+ // We should only dereference callbacks after being back to the Document/Worker threads.
+ context.postTask(
+ [output = WTFMove(*output), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) {
+ callback(output);
+ context.deref();
+ });
+ });
+}
+
+void CryptoAlgorithmRSASSA_PKCS1_v1_5::platformVerify(Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
+{
+ context.ref();
+ workQueue.dispatch(
+ [key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable {
+ auto& rsaKey = downcast<CryptoKeyRSA>(key.get());
+
+ auto output = gcryptVerify(rsaKey.platformKey(), signature, data, rsaKey.hashAlgorithmIdentifier());
+ if (!output) {
+ // We should only dereference callbacks after being back to the Document/Worker threads.
+ context.postTask(
+ [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) {
+ exceptionCallback(OperationError);
+ context.deref();
+ });
+ return;
+ }
+
+ // We should only dereference callbacks after being back to the Document/Worker threads.
+ context.postTask(
+ [output = WTFMove(*output), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) {
+ callback(output);
+ context.deref();
+ });
+ });
}
ExceptionOr<void> CryptoAlgorithmRSASSA_PKCS1_v1_5::platformSign(const CryptoAlgorithmRsaSsaParamsDeprecated&, const CryptoKeyRSA&, const CryptoOperationData&, VectorCallback&&, VoidCallback&&)