summaryrefslogtreecommitdiffstats
path: root/content/child/webcrypto/openssl
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-18 20:19:34 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-18 20:19:34 +0000
commitd008566b720e4d41fb0fdc83d2b7f3b74ce39c02 (patch)
tree816ecde55aaf3c3ec81b3a4839f6dac5fcfef53c /content/child/webcrypto/openssl
parentb31dbfcc5310f4056950e874efbfc513955c47bf (diff)
downloadchromium_src-d008566b720e4d41fb0fdc83d2b7f3b74ce39c02.zip
chromium_src-d008566b720e4d41fb0fdc83d2b7f3b74ce39c02.tar.gz
chromium_src-d008566b720e4d41fb0fdc83d2b7f3b74ce39c02.tar.bz2
Refactor WebCrypto code.
Split up the monstrously large platform_crypto_nss.cc, platform_crypto_openssl.cc into multiple files. ----------- Overview: ----------- * algorithm_implementation.h: This defines a base class AlgorithmImplementation, which has virtual methods for synchronous encrypt/decrypt/generatekey. All of the information about an algorithm is now encapsulated by an AlgorithmImplementation. So for instance the JWK specific knowledge, key usages for each key type are pulled into this interface. * algorithm_registry.cc: Contains a mapping from WebCryptoAlgorithmID --> AlgorithmImplementation, stored by a singleton. * algorithm_dispatch.cc: Given parameters from Blink, looks up the appropriate AlgorithmImplementation in the registry and dispatches the operation. Also implements wrap/unwrap in terms of encrypt/decrypt. * structured_clone.cc: Contains the code related to structured cloning (which still needs some cleanup, and is implemented in terms of import/export). * nss/*, openssl/*: Contains the AlgorithmImplementation concrete classes for each algorithm. This reorganization also unintentionally fixes a few bugs. * ExportKey() for spki/pkcs8/raw uses the already serialized key data rather than re-exporting * Some exception codes were fixed. BUG=389325,389342,389327,374912 Review URL: https://codereview.chromium.org/379383002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284192 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/child/webcrypto/openssl')
-rw-r--r--content/child/webcrypto/openssl/aes_cbc_openssl.cc138
-rw-r--r--content/child/webcrypto/openssl/aes_gcm_openssl.cc142
-rw-r--r--content/child/webcrypto/openssl/aes_key_openssl.cc126
-rw-r--r--content/child/webcrypto/openssl/aes_key_openssl.h70
-rw-r--r--content/child/webcrypto/openssl/aes_kw_openssl.cc44
-rw-r--r--content/child/webcrypto/openssl/hmac_openssl.cc211
-rw-r--r--content/child/webcrypto/openssl/key_openssl.cc53
-rw-r--r--content/child/webcrypto/openssl/key_openssl.h56
-rw-r--r--content/child/webcrypto/openssl/sha_openssl.cc139
-rw-r--r--content/child/webcrypto/openssl/sym_key_openssl.cc58
-rw-r--r--content/child/webcrypto/openssl/sym_key_openssl.h33
-rw-r--r--content/child/webcrypto/openssl/util_openssl.cc48
-rw-r--r--content/child/webcrypto/openssl/util_openssl.h26
13 files changed, 1144 insertions, 0 deletions
diff --git a/content/child/webcrypto/openssl/aes_cbc_openssl.cc b/content/child/webcrypto/openssl/aes_cbc_openssl.cc
new file mode 100644
index 0000000..aaf0fc1
--- /dev/null
+++ b/content/child/webcrypto/openssl/aes_cbc_openssl.cc
@@ -0,0 +1,138 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) {
+ // BoringSSL does not support 192-bit AES keys.
+ switch (key_length_bytes) {
+ case 16:
+ return EVP_aes_128_cbc();
+ case 32:
+ return EVP_aes_256_cbc();
+ default:
+ return NULL;
+ }
+}
+
+// OpenSSL constants for EVP_CipherInit_ex(), do not change
+enum CipherOperation { kDoDecrypt = 0, kDoEncrypt = 1 };
+
+Status AesCbcEncryptDecrypt(CipherOperation cipher_operation,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) {
+ const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
+ const std::vector<uint8>& raw_key = SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ if (params->iv().size() != 16)
+ return Status::ErrorIncorrectSizeAesCbcIv();
+
+ if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
+ // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right
+ // now it doesn't make much difference since the one-shot API would end up
+ // blowing out the memory and crashing anyway.
+ return Status::ErrorDataTooLarge();
+ }
+
+ // Note: PKCS padding is enabled by default
+ crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>::Type context(
+ EVP_CIPHER_CTX_new());
+
+ if (!context.get())
+ return Status::OperationError();
+
+ const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size());
+ DCHECK(cipher);
+
+ if (!EVP_CipherInit_ex(context.get(),
+ cipher,
+ NULL,
+ &raw_key[0],
+ params->iv().data(),
+ cipher_operation)) {
+ return Status::OperationError();
+ }
+
+ // According to the openssl docs, the amount of data written may be as large
+ // as (data_size + cipher_block_size - 1), constrained to a multiple of
+ // cipher_block_size.
+ unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE - 1;
+ const unsigned remainder = output_max_len % AES_BLOCK_SIZE;
+ if (remainder != 0)
+ output_max_len += AES_BLOCK_SIZE - remainder;
+ DCHECK_GT(output_max_len, data.byte_length());
+
+ buffer->resize(output_max_len);
+
+ unsigned char* const buffer_data = Uint8VectorStart(buffer);
+
+ int output_len = 0;
+ if (!EVP_CipherUpdate(context.get(),
+ buffer_data,
+ &output_len,
+ data.bytes(),
+ data.byte_length()))
+ return Status::OperationError();
+ int final_output_chunk_len = 0;
+ if (!EVP_CipherFinal_ex(
+ context.get(), buffer_data + output_len, &final_output_chunk_len)) {
+ return Status::OperationError();
+ }
+
+ const unsigned int final_output_len =
+ static_cast<unsigned int>(output_len) +
+ static_cast<unsigned int>(final_output_chunk_len);
+ DCHECK_LE(final_output_len, output_max_len);
+
+ buffer->resize(final_output_len);
+
+ return Status::Success();
+}
+
+class AesCbcImplementation : public AesAlgorithm {
+ public:
+ AesCbcImplementation() : AesAlgorithm("CBC") {}
+
+ virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ return AesCbcEncryptDecrypt(kDoEncrypt, algorithm, key, data, buffer);
+ }
+
+ virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ return AesCbcEncryptDecrypt(kDoDecrypt, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesCbcImplementation() {
+ return new AesCbcImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/aes_gcm_openssl.cc b/content/child/webcrypto/openssl/aes_gcm_openssl.cc
new file mode 100644
index 0000000..b29ad90
--- /dev/null
+++ b/content/child/webcrypto/openssl/aes_gcm_openssl.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_AEAD* GetAesGcmAlgorithmFromKeySize(unsigned int key_size_bytes) {
+ switch (key_size_bytes) {
+ case 16:
+ return EVP_aead_aes_128_gcm();
+ // TODO(eroman): Hook up 256-bit support when it is available.
+ default:
+ return NULL;
+ }
+}
+
+Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) {
+ const std::vector<uint8>& raw_key = SymKeyOpenSsl::Cast(key)->raw_key_data();
+ const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ unsigned int tag_length_bits;
+ Status status = GetAesGcmTagLengthInBits(params, &tag_length_bits);
+ if (status.IsError())
+ return status;
+ unsigned int tag_length_bytes = tag_length_bits / 8;
+
+ CryptoData iv(params->iv());
+ CryptoData additional_data(params->optionalAdditionalData());
+
+ EVP_AEAD_CTX ctx;
+
+ const EVP_AEAD* const aead_alg =
+ GetAesGcmAlgorithmFromKeySize(raw_key.size());
+ if (!aead_alg)
+ return Status::ErrorUnexpected();
+
+ if (!EVP_AEAD_CTX_init(&ctx,
+ aead_alg,
+ Uint8VectorStart(raw_key),
+ raw_key.size(),
+ tag_length_bytes,
+ NULL)) {
+ return Status::OperationError();
+ }
+
+ crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup>::Type ctx_cleanup(
+ &ctx);
+
+ size_t len;
+ int ok;
+
+ if (mode == DECRYPT) {
+ if (data.byte_length() < tag_length_bytes)
+ return Status::ErrorDataTooSmall();
+
+ buffer->resize(data.byte_length() - tag_length_bytes);
+
+ ok = EVP_AEAD_CTX_open(&ctx,
+ Uint8VectorStart(buffer),
+ &len,
+ buffer->size(),
+ iv.bytes(),
+ iv.byte_length(),
+ data.bytes(),
+ data.byte_length(),
+ additional_data.bytes(),
+ additional_data.byte_length());
+ } else {
+ // No need to check for unsigned integer overflow here (seal fails if
+ // the output buffer is too small).
+ buffer->resize(data.byte_length() + tag_length_bytes);
+
+ ok = EVP_AEAD_CTX_seal(&ctx,
+ Uint8VectorStart(buffer),
+ &len,
+ buffer->size(),
+ iv.bytes(),
+ iv.byte_length(),
+ data.bytes(),
+ data.byte_length(),
+ additional_data.bytes(),
+ additional_data.byte_length());
+ }
+
+ if (!ok)
+ return Status::OperationError();
+ buffer->resize(len);
+ return Status::Success();
+}
+
+class AesGcmImplementation : public AesAlgorithm {
+ public:
+ AesGcmImplementation() : AesAlgorithm("GCM") {}
+
+ virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ return AesGcmEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ return AesGcmEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesGcmImplementation() {
+ return new AesGcmImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/aes_key_openssl.cc b/content/child/webcrypto/openssl/aes_key_openssl.cc
new file mode 100644
index 0000000..f6fda3a
--- /dev/null
+++ b/content/child/webcrypto/openssl/aes_key_openssl.cc
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/sym_key_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+AesAlgorithm::AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix)
+ : all_key_usages_(all_key_usages), jwk_suffix_(jwk_suffix) {
+}
+
+AesAlgorithm::AesAlgorithm(const std::string& jwk_suffix)
+ : all_key_usages_(blink::WebCryptoKeyUsageEncrypt |
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageWrapKey |
+ blink::WebCryptoKeyUsageUnwrapKey),
+ jwk_suffix_(jwk_suffix) {
+}
+
+Status AesAlgorithm::VerifyKeyUsagesBeforeGenerateKey(
+ blink::WebCryptoKeyUsageMask usage_mask) const {
+ return CheckKeyCreationUsages(all_key_usages_, usage_mask);
+}
+
+Status AesAlgorithm::GenerateSecretKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const {
+ unsigned int keylen_bits;
+ Status status =
+ GetAesKeyGenLengthInBits(algorithm.aesKeyGenParams(), &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyOpenSsl(
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usage_mask,
+ keylen_bits / 8,
+ key);
+}
+
+Status AesAlgorithm::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usage_mask) const {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(all_key_usages_, usage_mask);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+}
+
+Status AesAlgorithm::ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const {
+ const unsigned int keylen_bytes = key_data.byte_length();
+ Status status = VerifyAesKeyLengthForImport(keylen_bytes);
+ if (status.IsError())
+ return status;
+
+ // No possibility of overflow.
+ unsigned int keylen_bits = keylen_bytes * 8;
+
+ return ImportKeyRawOpenSsl(
+ key_data,
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usage_mask,
+ key);
+}
+
+Status AesAlgorithm::ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const {
+ std::vector<uint8> raw_data;
+ Status status = ReadAesSecretKeyJwk(
+ key_data, jwk_suffix_, extractable, usage_mask, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usage_mask, key);
+}
+
+Status AesAlgorithm::ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const {
+ *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
+ return Status::Success();
+}
+
+Status AesAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const {
+ const std::vector<uint8>& raw_data = SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ MakeJwkAesAlgorithmName(jwk_suffix_, raw_data.size()),
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/aes_key_openssl.h b/content/child/webcrypto/openssl/aes_key_openssl.h
new file mode 100644
index 0000000..d5a74ff
--- /dev/null
+++ b/content/child/webcrypto/openssl/aes_key_openssl.h
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// Base class for AES algorithms that provides the implementation for key
+// creation and export.
+class AesAlgorithm : public AlgorithmImplementation {
+ public:
+ // |all_key_usages| is the set of all WebCrypto key usages that are
+ // allowed for imported or generated keys. |jwk_suffix| is the suffix
+ // used when constructing JWK names for the algorithm. For instance A128CBC
+ // is the JWK name for 128-bit AES-CBC. The |jwk_suffix| in this case would
+ // be "CBC".
+ AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix);
+
+ // This is the same as the other AesAlgorithm constructor where
+ // |all_key_usages| is pre-filled to values for encryption/decryption
+ // algorithms (supports usages for: encrypt, decrypt, wrap, unwrap).
+ explicit AesAlgorithm(const std::string& jwk_suffix);
+
+ virtual Status VerifyKeyUsagesBeforeGenerateKey(
+ blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE;
+
+ virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE;
+
+ virtual Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE;
+
+ virtual Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE;
+
+ virtual Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE;
+
+ virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const OVERRIDE;
+
+ virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const OVERRIDE;
+
+ private:
+ const blink::WebCryptoKeyUsageMask all_key_usages_;
+ const std::string jwk_suffix_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
diff --git a/content/child/webcrypto/openssl/aes_kw_openssl.cc b/content/child/webcrypto/openssl/aes_kw_openssl.cc
new file mode 100644
index 0000000..d2bb10f
--- /dev/null
+++ b/content/child/webcrypto/openssl/aes_kw_openssl.cc
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/status.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+class AesKwImplementation : public AesAlgorithm {
+ public:
+ AesKwImplementation() : AesAlgorithm("KW") {}
+
+ virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ // TODO(eroman):
+ return Status::ErrorUnsupported();
+ }
+
+ virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ // TODO(eroman):
+ return Status::ErrorUnsupported();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesKwImplementation() {
+ return new AesKwImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/hmac_openssl.cc b/content/child/webcrypto/openssl/hmac_openssl.cc
new file mode 100644
index 0000000..a40bfd9
--- /dev/null
+++ b/content/child/webcrypto/openssl/hmac_openssl.cc
@@ -0,0 +1,211 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <openssl/hmac.h>
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/sym_key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const blink::WebCryptoKeyUsageMask kAllKeyUsages =
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+
+Status SignHmac(const std::vector<uint8>& raw_key,
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ const EVP_MD* digest_algorithm = GetDigest(hash.id());
+ if (!digest_algorithm)
+ return Status::ErrorUnsupported();
+ unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
+
+ // OpenSSL wierdness here.
+ // First, HMAC() needs a void* for the key data, so make one up front as a
+ // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
+ // which will result if the raw_key vector is empty; an entirely valid
+ // case. Handle this specific case by pointing to an empty array.
+ const unsigned char null_key[] = {};
+ const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
+
+ buffer->resize(hmac_expected_length);
+ crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
+ Uint8VectorStart(buffer), hmac_expected_length);
+
+ unsigned int hmac_actual_length;
+ unsigned char* const success = HMAC(digest_algorithm,
+ raw_key_voidp,
+ raw_key.size(),
+ data.bytes(),
+ data.byte_length(),
+ hmac_result.safe_buffer(),
+ &hmac_actual_length);
+ if (!success || hmac_actual_length != hmac_expected_length)
+ return Status::OperationError();
+
+ return Status::Success();
+}
+
+class HmacImplementation : public AlgorithmImplementation {
+ public:
+ HmacImplementation() {}
+
+ virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE {
+ const blink::WebCryptoHmacKeyGenParams* params =
+ algorithm.hmacKeyGenParams();
+
+ unsigned int keylen_bits = 0;
+ Status status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyOpenSsl(blink::WebCryptoKeyAlgorithm::createHmac(
+ params->hash().id(), keylen_bits),
+ extractable,
+ usage_mask,
+ keylen_bits / 8,
+ key);
+ }
+
+ virtual Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+ }
+
+ virtual Status VerifyKeyUsagesBeforeGenerateKey(
+ blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
+ return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
+ }
+
+ virtual Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE {
+ const blink::WebCryptoAlgorithm& hash =
+ algorithm.hmacImportParams()->hash();
+
+ // TODO(eroman): check for overflow.
+ unsigned int keylen_bits = key_data.byte_length() * 8;
+
+ return ImportKeyRawOpenSsl(
+ key_data,
+ blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
+ extractable,
+ usage_mask,
+ key);
+ }
+
+ virtual Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) const OVERRIDE {
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ std::vector<uint8> raw_data;
+ Status status = ReadSecretKeyJwk(
+ key_data, algorithm_name, extractable, usage_mask, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usage_mask, key);
+ }
+
+ virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
+ return Status::Success();
+ }
+
+ virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ SymKeyOpenSsl* sym_key = SymKeyOpenSsl::Cast(key);
+ const std::vector<uint8>& raw_data = sym_key->raw_key_data();
+
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ algorithm_name,
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+ }
+
+ virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ const blink::WebCryptoAlgorithm& hash =
+ key.algorithm().hmacParams()->hash();
+
+ return SignHmac(
+ SymKeyOpenSsl::Cast(key)->raw_key_data(), hash, data, buffer);
+ }
+
+ virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const OVERRIDE {
+ std::vector<uint8> result;
+ Status status = Sign(algorithm, key, data, &result);
+
+ if (status.IsError())
+ return status;
+
+ // Do not allow verification of truncated MACs.
+ *signature_match = result.size() == signature.byte_length() &&
+ crypto::SecureMemEqual(Uint8VectorStart(result),
+ signature.bytes(),
+ signature.byte_length());
+
+ return Status::Success();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformHmacImplementation() {
+ return new HmacImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/key_openssl.cc b/content/child/webcrypto/openssl/key_openssl.cc
new file mode 100644
index 0000000..ebd45e2
--- /dev/null
+++ b/content/child/webcrypto/openssl/key_openssl.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/webcrypto/openssl/key_openssl.h"
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+
+namespace content {
+
+namespace webcrypto {
+
+KeyOpenSsl::KeyOpenSsl(const CryptoData& serialized_key_data)
+ : serialized_key_data_(
+ serialized_key_data.bytes(),
+ serialized_key_data.bytes() + serialized_key_data.byte_length()) {
+}
+
+KeyOpenSsl::~KeyOpenSsl() {
+}
+
+SymKeyOpenSsl* KeyOpenSsl::AsSymKey() {
+ return NULL;
+}
+
+SymKeyOpenSsl::~SymKeyOpenSsl() {
+}
+
+SymKeyOpenSsl* SymKeyOpenSsl::Cast(const blink::WebCryptoKey& key) {
+ KeyOpenSsl* platform_key = reinterpret_cast<KeyOpenSsl*>(key.handle());
+ return platform_key->AsSymKey();
+}
+
+SymKeyOpenSsl* SymKeyOpenSsl::AsSymKey() {
+ return this;
+}
+
+SymKeyOpenSsl::SymKeyOpenSsl(const CryptoData& raw_key_data)
+ : KeyOpenSsl(raw_key_data) {
+}
+
+bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8>* key_data) {
+ const KeyOpenSsl* openssl_key = static_cast<KeyOpenSsl*>(key.handle());
+ *key_data = openssl_key->serialized_key_data();
+ return true;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/key_openssl.h b/content/child/webcrypto/openssl/key_openssl.h
new file mode 100644
index 0000000..ef32438
--- /dev/null
+++ b/content/child/webcrypto/openssl/key_openssl.h
@@ -0,0 +1,56 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class SymKeyOpenSsl;
+
+// Base key class for all OpenSSL keys, used to safely cast between types. Each
+// key maintains a copy of its serialized form in either 'raw', 'pkcs8', or
+// 'spki' format. This is to allow structured cloning of keys synchronously from
+// the target Blink thread without having to lock access to the key.
+class KeyOpenSsl : public blink::WebCryptoKeyHandle {
+ public:
+ explicit KeyOpenSsl(const CryptoData& serialized_key_data);
+ virtual ~KeyOpenSsl();
+
+ virtual SymKeyOpenSsl* AsSymKey();
+
+ const std::vector<uint8>& serialized_key_data() const {
+ return serialized_key_data_;
+ }
+
+ private:
+ const std::vector<uint8> serialized_key_data_;
+};
+
+class SymKeyOpenSsl : public KeyOpenSsl {
+ public:
+ virtual ~SymKeyOpenSsl();
+ explicit SymKeyOpenSsl(const CryptoData& raw_key_data);
+
+ static SymKeyOpenSsl* Cast(const blink::WebCryptoKey& key);
+
+ virtual SymKeyOpenSsl* AsSymKey() OVERRIDE;
+
+ const std::vector<uint8>& raw_key_data() const {
+ return serialized_key_data();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SymKeyOpenSsl);
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
diff --git a/content/child/webcrypto/openssl/sha_openssl.cc b/content/child/webcrypto/openssl/sha_openssl.cc
new file mode 100644
index 0000000..f9382b5
--- /dev/null
+++ b/content/child/webcrypto/openssl/sha_openssl.cc
@@ -0,0 +1,139 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include "base/logging.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Implementation of blink::WebCryptoDigester, an internal Blink detail not
+// part of WebCrypto, that allows chunks of data to be streamed in before
+// computing a SHA-* digest (as opposed to ShaImplementation, which computes
+// digests over complete messages)
+class DigestorOpenSsl : public blink::WebCryptoDigestor {
+ public:
+ explicit DigestorOpenSsl(blink::WebCryptoAlgorithmId algorithm_id)
+ : initialized_(false),
+ digest_context_(EVP_MD_CTX_create()),
+ algorithm_id_(algorithm_id) {}
+
+ virtual bool consume(const unsigned char* data, unsigned int size) {
+ return ConsumeWithStatus(data, size).IsSuccess();
+ }
+
+ Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+
+ if (!EVP_DigestUpdate(digest_context_.get(), data, size))
+ return Status::OperationError();
+
+ return Status::Success();
+ }
+
+ virtual bool finish(unsigned char*& result_data,
+ unsigned int& result_data_size) {
+ Status error = FinishInternal(result_, &result_data_size);
+ if (!error.IsSuccess())
+ return false;
+ result_data = result_;
+ return true;
+ }
+
+ Status FinishWithVectorAndStatus(std::vector<uint8>* result) {
+ const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
+ result->resize(hash_expected_size);
+ unsigned char* const hash_buffer = Uint8VectorStart(result);
+ unsigned int hash_buffer_size; // ignored
+ return FinishInternal(hash_buffer, &hash_buffer_size);
+ }
+
+ private:
+ Status Init() {
+ if (initialized_)
+ return Status::Success();
+
+ const EVP_MD* digest_algorithm = GetDigest(algorithm_id_);
+ if (!digest_algorithm)
+ return Status::ErrorUnexpected();
+
+ if (!digest_context_.get())
+ return Status::OperationError();
+
+ if (!EVP_DigestInit_ex(digest_context_.get(), digest_algorithm, NULL))
+ return Status::OperationError();
+
+ initialized_ = true;
+ return Status::Success();
+ }
+
+ Status FinishInternal(unsigned char* result, unsigned int* result_size) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+
+ const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
+ if (hash_expected_size <= 0)
+ return Status::ErrorUnexpected();
+ DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE);
+
+ if (!EVP_DigestFinal_ex(digest_context_.get(), result, result_size) ||
+ static_cast<int>(*result_size) != hash_expected_size)
+ return Status::OperationError();
+
+ return Status::Success();
+ }
+
+ bool initialized_;
+ crypto::ScopedEVP_MD_CTX digest_context_;
+ blink::WebCryptoAlgorithmId algorithm_id_;
+ unsigned char result_[EVP_MAX_MD_SIZE];
+};
+
+class ShaImplementation : public AlgorithmImplementation {
+ public:
+ virtual Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) const OVERRIDE {
+ DigestorOpenSsl digestor(algorithm.id());
+ Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
+ // http://crbug.com/366427: the spec does not define any other failures for
+ // digest, so none of the subsequent errors are spec compliant.
+ if (!error.IsSuccess())
+ return error;
+ return digestor.FinishWithVectorAndStatus(buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformShaImplementation() {
+ return new ShaImplementation();
+}
+
+scoped_ptr<blink::WebCryptoDigestor> CreatePlatformDigestor(
+ blink::WebCryptoAlgorithmId algorithm) {
+ return scoped_ptr<blink::WebCryptoDigestor>(new DigestorOpenSsl(algorithm));
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/sym_key_openssl.cc b/content/child/webcrypto/openssl/sym_key_openssl.cc
new file mode 100644
index 0000000..e07db69
--- /dev/null
+++ b/content/child/webcrypto/openssl/sym_key_openssl.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/webcrypto/openssl/sym_key_openssl.h"
+
+#include <vector>
+#include <openssl/rand.h>
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+Status GenerateSecretKeyOpenSsl(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ unsigned keylen_bytes,
+ blink::WebCryptoKey* key) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ std::vector<unsigned char> random_bytes(keylen_bytes, 0);
+
+ if (keylen_bytes > 0) {
+ if (!(RAND_bytes(&random_bytes[0], keylen_bytes)))
+ return Status::OperationError();
+ }
+
+ *key =
+ blink::WebCryptoKey::create(new SymKeyOpenSsl(CryptoData(random_bytes)),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usage_mask);
+ return Status::Success();
+}
+
+Status ImportKeyRawOpenSsl(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+ *key = blink::WebCryptoKey::create(new SymKeyOpenSsl(key_data),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usage_mask);
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/sym_key_openssl.h b/content/child/webcrypto/openssl/sym_key_openssl.h
new file mode 100644
index 0000000..e952dee
--- /dev/null
+++ b/content/child/webcrypto/openssl/sym_key_openssl.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
+
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class Status;
+
+Status GenerateSecretKeyOpenSsl(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ unsigned keylen_bytes,
+ blink::WebCryptoKey* key);
+
+Status ImportKeyRawOpenSsl(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
diff --git a/content/child/webcrypto/openssl/util_openssl.cc b/content/child/webcrypto/openssl/util_openssl.cc
new file mode 100644
index 0000000..110057e
--- /dev/null
+++ b/content/child/webcrypto/openssl/util_openssl.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/webcrypto/openssl/util_openssl.h"
+
+#include <openssl/evp.h>
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "crypto/openssl_util.h"
+
+namespace content {
+
+namespace webcrypto {
+
+void PlatformInit() {
+ crypto::EnsureOpenSSLInit();
+}
+
+const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) {
+ switch (id) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return EVP_sha1();
+ case blink::WebCryptoAlgorithmIdSha256:
+ return EVP_sha256();
+ case blink::WebCryptoAlgorithmIdSha384:
+ return EVP_sha384();
+ case blink::WebCryptoAlgorithmIdSha512:
+ return EVP_sha512();
+ default:
+ return NULL;
+ }
+}
+
+AlgorithmImplementation* CreatePlatformRsaOaepImplementation() {
+ // TODO(eroman):
+ return NULL;
+}
+
+AlgorithmImplementation* CreatePlatformRsaSsaImplementation() {
+ // TODO(eroman):
+ return NULL;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/content/child/webcrypto/openssl/util_openssl.h b/content/child/webcrypto/openssl/util_openssl.h
new file mode 100644
index 0000000..15d3308
--- /dev/null
+++ b/content/child/webcrypto/openssl/util_openssl.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_
+
+#include <openssl/ossl_typ.h>
+
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+
+enum EncryptOrDecrypt { ENCRYPT, DECRYPT };
+
+const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_