#include <openssl/sha.h>
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "content/child/webcrypto/crypto_data.h"
#include "content/child/webcrypto/status.h"
#include "content/child/webcrypto/webcrypto_util.h"
#include "crypto/openssl_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"
#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
virtual SymKey* AsSymKey() OVERRIDE { return this; }
virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
+ virtual bool ThreadSafeSerializeForClone(
+ blink::WebVector<uint8>* key_data) OVERRIDE {
+ key_data->assign(Uint8VectorStart(key_), key_.size());
+ return true;
+ }
const std::vector<unsigned char>& key() const { return key_; }
SymKey* key,
const CryptoData& iv,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
CipherOperation cipher_operation =
(mode == ENCRYPT) ? kDoEncrypt : kDoDecrypt;
EVP_CIPHER_CTX_new());
if (!context.get())
- return Status::Error();
+ return Status::OperationError();
const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(key->key().size());
DCHECK(cipher);
&key->key()[0],
iv.bytes(),
cipher_operation)) {
- return Status::Error();
+ return Status::OperationError();
}
// According to the openssl docs, the amount of data written may be as large
output_max_len += AES_BLOCK_SIZE - remainder;
DCHECK_GT(output_max_len, data.byte_length());
- *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
+ buffer->resize(output_max_len);
- unsigned char* const buffer_data =
- reinterpret_cast<unsigned char*>(buffer->data());
+ unsigned char* const buffer_data = Uint8VectorStart(buffer);
int output_len = 0;
if (!EVP_CipherUpdate(context.get(),
&output_len,
data.bytes(),
data.byte_length()))
- return Status::Error();
+ 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::Error();
+ return Status::OperationError();
}
const unsigned int final_output_len =
static_cast<unsigned int>(final_output_chunk_len);
DCHECK_LE(final_output_len, output_max_len);
- ShrinkBuffer(buffer, final_output_len);
+ buffer->resize(final_output_len);
return Status::Success();
}
} // namespace
-Status ExportKeyRaw(SymKey* key, blink::WebArrayBuffer* buffer) {
- *buffer = CreateArrayBuffer(Uint8VectorStart(key->key()), key->key().size());
+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(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(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::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context_;
+ blink::WebCryptoAlgorithmId algorithm_id_;
+ unsigned char result_[EVP_MAX_MD_SIZE];
+};
+
+Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer) {
+ *buffer = key->key();
return Status::Success();
}
SymKey* key,
const CryptoData& data,
const CryptoData& iv,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): inline the function here.
return AesCbcEncryptDecrypt(mode, key, iv, data, buffer);
}
Status DigestSha(blink::WebCryptoAlgorithmId algorithm,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
- crypto::OpenSSLErrStackTracer(FROM_HERE);
-
- const EVP_MD* digest_algorithm = GetDigest(algorithm);
- if (!digest_algorithm)
- return Status::ErrorUnexpected();
-
- crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context(
- EVP_MD_CTX_create());
- if (!digest_context.get())
- return Status::Error();
-
- if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) ||
- !EVP_DigestUpdate(
- digest_context.get(), data.bytes(), data.byte_length())) {
- return Status::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);
-
- *buffer = blink::WebArrayBuffer::create(hash_expected_size, 1);
- unsigned char* const hash_buffer =
- reinterpret_cast<unsigned char* const>(buffer->data());
-
- unsigned int hash_size = 0;
- if (!EVP_DigestFinal_ex(digest_context.get(), hash_buffer, &hash_size) ||
- static_cast<int>(hash_size) != hash_expected_size) {
- buffer->reset();
- return Status::Error();
- }
+ std::vector<uint8>* buffer) {
+ DigestorOpenSSL digestor(algorithm);
+ Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
+ if (!error.IsSuccess())
+ return error;
+ return digestor.FinishWithVectorAndStatus(buffer);
+}
- return Status::Success();
+scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
+ blink::WebCryptoAlgorithmId algorithm_id) {
+ return scoped_ptr<blink::WebCryptoDigestor>(
+ new DigestorOpenSSL(algorithm_id));
}
Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
std::vector<unsigned char> random_bytes(keylen_bytes, 0);
if (!(RAND_bytes(&random_bytes[0], keylen_bytes)))
- return Status::Error();
+ return Status::OperationError();
blink::WebCryptoKeyAlgorithm key_algorithm;
if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm))
Status SignHmac(SymKey* key,
const blink::WebCryptoAlgorithm& hash,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
- blink::WebArrayBuffer result;
-
+ std::vector<uint8>* buffer) {
const EVP_MD* digest_algorithm = GetDigest(hash.id());
if (!digest_algorithm)
return Status::ErrorUnsupported();
const unsigned char null_key[] = {};
const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
- result = blink::WebArrayBuffer::create(hmac_expected_length, 1);
+ buffer->resize(hmac_expected_length);
crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
- reinterpret_cast<unsigned char*>(result.data()), hmac_expected_length);
+ Uint8VectorStart(buffer), hmac_expected_length);
crypto::OpenSSLErrStackTracer(FROM_HERE);
hmac_result.safe_buffer(),
&hmac_actual_length);
if (!success || hmac_actual_length != hmac_expected_length)
- return Status::Error();
+ return Status::OperationError();
- *buffer = result;
return Status::Success();
}
const CryptoData& iv,
const CryptoData& additional_data,
unsigned int tag_length_bits,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
// Guaranteed that key is valid.
Status EncryptRsaEsPkcs1v1_5(PublicKey* key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status DecryptRsaEsPkcs1v1_5(PrivateKey* key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status SignRsaSsaPkcs1v1_5(PrivateKey* key,
const blink::WebCryptoAlgorithm& hash,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
return Status::ErrorUnsupported();
}
-Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) {
+Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status ExportKeyPkcs8(PrivateKey* key,
const blink::WebCryptoKeyAlgorithm& key_algorithm,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status WrapSymKeyAesKw(SymKey* wrapping_key,
SymKey* key,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status DecryptAesKw(SymKey* key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
Status WrapSymKeyRsaEs(PublicKey* wrapping_key,
SymKey* key,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// TODO(eroman): http://crbug.com/267888
return Status::ErrorUnsupported();
}
return Status::ErrorUnsupported();
}
+bool ThreadSafeDeserializeKeyForClone(
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const CryptoData& key_data,
+ blink::WebCryptoKey* key) {
+ // TODO(eroman): http://crbug.com/267888
+ return false;
+}
+
} // namespace platform
} // namespace webcrypto