Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1730)

Unified Diff: content/renderer/webcrypto/webcrypto_impl_openssl.cc

Issue 24276011: WebCrypto: Implement importKey(), sign(), and verify() for HMAC in OpenSSL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/content_tests.gypi ('k') | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/webcrypto/webcrypto_impl_openssl.cc
diff --git a/content/renderer/webcrypto/webcrypto_impl_openssl.cc b/content/renderer/webcrypto/webcrypto_impl_openssl.cc
index 040c174a62b0c85c6598158d9d8a61761e6eaf28..767d840dc00a42803046e4e918ce157c4c7b0a70 100644
--- a/content/renderer/webcrypto/webcrypto_impl_openssl.cc
+++ b/content/renderer/webcrypto/webcrypto_impl_openssl.cc
@@ -4,10 +4,37 @@
#include "content/renderer/webcrypto/webcrypto_impl.h"
+#include <vector>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+#include "base/logging.h"
+#include "crypto/openssl_util.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
namespace content {
-void WebCryptoImpl::Init() {
-}
+namespace {
+
+class SymKeyHandle : public WebKit::WebCryptoKeyHandle {
+ public:
+ SymKeyHandle(const unsigned char* key_data, unsigned key_data_size)
+ : key_(key_data, key_data + key_data_size) {}
+
+ const std::vector<unsigned char>& key() const { return key_; }
+
+ private:
+ const std::vector<unsigned char> key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
+};
+
+} // anonymous namespace
+
+void WebCryptoImpl::Init() { crypto::EnsureOpenSSLInit(); }
bool WebCryptoImpl::EncryptInternal(
const WebKit::WebCryptoAlgorithm& algorithm,
@@ -15,6 +42,8 @@ bool WebCryptoImpl::EncryptInternal(
const unsigned char* data,
unsigned data_size,
WebKit::WebArrayBuffer* buffer) {
+ // TODO(padolph): Placeholder for OpenSSL implementation.
+ // Issue http://crbug.com/267888.
return false;
}
@@ -32,7 +61,7 @@ bool WebCryptoImpl::DigestInternal(
const unsigned char* data,
unsigned data_size,
WebKit::WebArrayBuffer* buffer) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
+ // TODO(padolph): Placeholder for OpenSSL implementation.
// Issue http://crbug.com/267888.
return false;
}
@@ -42,12 +71,45 @@ bool WebCryptoImpl::ImportKeyInternal(
const unsigned char* key_data,
unsigned key_data_size,
const WebKit::WebCryptoAlgorithm& algorithm,
- WebKit::WebCryptoKeyUsageMask usage_mask,
+ WebKit::WebCryptoKeyUsageMask /*usage_mask*/,
scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
WebKit::WebCryptoKeyType* type) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
+
+ // TODO(padolph): Support all relevant alg types and then remove this gate.
+ if (algorithm.id() != WebKit::WebCryptoAlgorithmIdHmac &&
+ algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) {
+ return false;
+ }
+
+ // TODO(padolph): Need to split handling for symmetric (raw or jwk format) and
+ // asymmetric (jwk, spki, or pkcs8 format) keys.
+ // Currently only supporting symmetric.
+
+ // TODO(padolph): jwk handling. Define precedence between jwk contents and
+ // this method's parameters, e.g. 'alg' in jwk vs algorithm.id(). Who wins if
+ // they differ? (jwk, probably)
+
+ // Symmetric keys are always type secret
+ *type = WebKit::WebCryptoKeyTypeSecret;
+
+ const unsigned char* raw_key_data;
+ unsigned raw_key_data_size;
+ switch (format) {
+ case WebKit::WebCryptoKeyFormatRaw:
+ raw_key_data = key_data;
+ raw_key_data_size = key_data_size;
+ break;
+ case WebKit::WebCryptoKeyFormatJwk:
+ // TODO(padolph): Handle jwk format; need simple JSON parser.
+ // break;
+ return false;
+ default:
+ return false;
+ }
+
+ handle->reset(new SymKeyHandle(raw_key_data, raw_key_data_size));
+
+ return true;
}
bool WebCryptoImpl::SignInternal(
@@ -56,9 +118,86 @@ bool WebCryptoImpl::SignInternal(
const unsigned char* data,
unsigned data_size,
WebKit::WebArrayBuffer* buffer) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
+
+ WebKit::WebArrayBuffer result;
+
+ switch (algorithm.id()) {
+ case WebKit::WebCryptoAlgorithmIdHmac: {
+
+ DCHECK_EQ(key.algorithm().id(), WebKit::WebCryptoAlgorithmIdHmac);
+ DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign);
+
+ const WebKit::WebCryptoHmacParams* const params = algorithm.hmacParams();
+ if (!params)
+ return false;
+
+ const EVP_MD* evp_sha = 0;
+ unsigned int hmac_expected_length = 0;
+ // Note that HMAC length is determined by the hash used.
+ switch (params->hash().id()) {
+ case WebKit::WebCryptoAlgorithmIdSha1:
+ evp_sha = EVP_sha1();
+ hmac_expected_length = SHA_DIGEST_LENGTH;
+ break;
+ case WebKit::WebCryptoAlgorithmIdSha224:
+ evp_sha = EVP_sha224();
+ hmac_expected_length = SHA224_DIGEST_LENGTH;
+ break;
+ case WebKit::WebCryptoAlgorithmIdSha256:
+ evp_sha = EVP_sha256();
+ hmac_expected_length = SHA256_DIGEST_LENGTH;
+ break;
+ case WebKit::WebCryptoAlgorithmIdSha384:
+ evp_sha = EVP_sha384();
+ hmac_expected_length = SHA384_DIGEST_LENGTH;
+ break;
+ case WebKit::WebCryptoAlgorithmIdSha512:
+ evp_sha = EVP_sha512();
+ hmac_expected_length = SHA512_DIGEST_LENGTH;
+ break;
+ default:
+ // Not a digest algorithm.
+ return false;
+ }
+
+ SymKeyHandle* const sym_key =
+ reinterpret_cast<SymKeyHandle*>(key.handle());
+ const std::vector<unsigned char>& raw_key = sym_key->key();
+
+ // 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;
+
+ result = WebKit::WebArrayBuffer::create(hmac_expected_length, 1);
+ crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
+ reinterpret_cast<unsigned char*>(result.data()),
+ hmac_expected_length);
+
+ crypto::OpenSSLErrStackTracer(FROM_HERE);
+
+ unsigned int hmac_actual_length;
+ unsigned char* const success = HMAC(evp_sha,
+ raw_key_voidp,
+ raw_key.size(),
+ data,
+ data_size,
+ hmac_result.safe_buffer(),
+ &hmac_actual_length);
+ if (!success || hmac_actual_length != hmac_expected_length)
+ return false;
+
+ break;
+ }
+ default:
+ return false;
+ }
+
+ *buffer = result;
+ return true;
}
bool WebCryptoImpl::VerifySignatureInternal(
@@ -69,9 +208,27 @@ bool WebCryptoImpl::VerifySignatureInternal(
const unsigned char* data,
unsigned data_size,
bool* signature_match) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
+ switch (algorithm.id()) {
+ case WebKit::WebCryptoAlgorithmIdHmac: {
+ WebKit::WebArrayBuffer result;
+ if (!SignInternal(algorithm, key, data, data_size, &result)) {
+ return false;
+ }
+
+ // Handling of truncated signatures is underspecified in the WebCrypto
+ // spec, so here we fail verification if a truncated signature is being
+ // verified.
+ // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
+ *signature_match =
+ result.byteLength() == signature_size &&
+ crypto::SecureMemEqual(result.data(), signature, signature_size);
+
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
}
} // namespace content
« no previous file with comments | « content/content_tests.gypi ('k') | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698