[GCrypt] Implement PBKDF2 support
authorzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Apr 2017 18:10:29 +0000 (18:10 +0000)
committerzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Apr 2017 18:10:29 +0000 (18:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170270

Reviewed by Michael Catanzaro.

Implement the CryptoAlgorithmPBKDF2::platformDeriveBits() functionality
for configurations that use libgcrypt. This is done by leveraging the
gcry_kdf_derive() API, using GCRY_KDF_PBKDF2 as the preferred KDF
along with the properly deducted SHA algorithm.

No new tests -- current ones cover this sufficiently, but are not yet
enabled due to other missing platform-specific SUBTLE_CRYPTO
implementations.

* crypto/gcrypt/CryptoAlgorithmPBKDF2GCrypt.cpp:
(WebCore::gcryptDeriveBits):
(WebCore::CryptoAlgorithmPBKDF2::platformDeriveBits):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214821 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/crypto/gcrypt/CryptoAlgorithmPBKDF2GCrypt.cpp

index fb820d1..df1db98 100644 (file)
@@ -1,3 +1,23 @@
+2017-04-03  Zan Dobersek  <zdobersek@igalia.com>
+
+        [GCrypt] Implement PBKDF2 support
+        https://bugs.webkit.org/show_bug.cgi?id=170270
+
+        Reviewed by Michael Catanzaro.
+
+        Implement the CryptoAlgorithmPBKDF2::platformDeriveBits() functionality
+        for configurations that use libgcrypt. This is done by leveraging the
+        gcry_kdf_derive() API, using GCRY_KDF_PBKDF2 as the preferred KDF
+        along with the properly deducted SHA algorithm.
+
+        No new tests -- current ones cover this sufficiently, but are not yet
+        enabled due to other missing platform-specific SUBTLE_CRYPTO
+        implementations.
+
+        * crypto/gcrypt/CryptoAlgorithmPBKDF2GCrypt.cpp:
+        (WebCore::gcryptDeriveBits):
+        (WebCore::CryptoAlgorithmPBKDF2::platformDeriveBits):
+
 2017-04-01  Simon Fraser  <simon.fraser@apple.com>
 
         Clean up touch event handler registration when moving nodes between documents
index b3cf173..5362003 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Metrological Group B.V.
+ * Copyright (C) 2017 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #if ENABLE(SUBTLE_CRYPTO)
 
-#include "NotImplemented.h"
+#include "CryptoAlgorithmPbkdf2Params.h"
+#include "CryptoKeyRaw.h"
+#include "ExceptionCode.h"
+#include "ScriptExecutionContext.h"
+#include <pal/crypto/gcrypt/Utilities.h>
 
 namespace WebCore {
 
-void CryptoAlgorithmPBKDF2::platformDeriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, size_t, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&)
+static std::optional<Vector<uint8_t>> gcryptDeriveBits(const Vector<uint8_t>& keyData, const Vector<uint8_t>& saltData, CryptoAlgorithmIdentifier hashIdentifier, size_t iterations, size_t length)
 {
-    notImplemented();
+    int hashAlgorithm;
+    switch (hashIdentifier) {
+    case CryptoAlgorithmIdentifier::SHA_1:
+        hashAlgorithm = GCRY_MD_SHA1;
+        break;
+    case CryptoAlgorithmIdentifier::SHA_224:
+        hashAlgorithm = GCRY_MD_SHA224;
+        break;
+    case CryptoAlgorithmIdentifier::SHA_256:
+        hashAlgorithm = GCRY_MD_SHA256;
+        break;
+    case CryptoAlgorithmIdentifier::SHA_384:
+        hashAlgorithm = GCRY_MD_SHA384;
+        break;
+    case CryptoAlgorithmIdentifier::SHA_512:
+        hashAlgorithm = GCRY_MD_SHA512;
+        break;
+    default:
+        return std::nullopt;
+    }
+
+    // Length, in bits, is a multiple of 8, as guaranteed by CryptoAlgorithmPBKDF2::deriveBits().
+    ASSERT(!(length % 8));
+
+    Vector<uint8_t> result(length / 8);
+    gcry_error_t error = gcry_kdf_derive(keyData.data(), keyData.size(), GCRY_KDF_PBKDF2, hashAlgorithm, saltData.data(), saltData.size(), iterations, result.size(), result.data());
+    if (error != GPG_ERR_NO_ERROR) {
+        PAL::GCrypt::logError(error);
+        return std::nullopt;
+    }
+
+    return result;
+}
+
+void CryptoAlgorithmPBKDF2::platformDeriveBits(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, size_t length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
+{
+    context.ref();
+    workQueue.dispatch(
+        [parameters = WTFMove(parameters), key = WTFMove(key), length, callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable {
+            auto& pbkdf2Parameters = downcast<CryptoAlgorithmPbkdf2Params>(*parameters);
+            auto& rawKey = downcast<CryptoKeyRaw>(key.get());
+
+            auto output = gcryptDeriveBits(rawKey.key(), pbkdf2Parameters.saltVector(), pbkdf2Parameters.hashIdentifier, pbkdf2Parameters.iterations, length);
+            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();
+                });
+        });
 }
 
 } // namespace WebCore