| Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
|
| diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
|
| index bcf636254aa907ded1866aa8ca97aca6ee42fc4a..d26a97568009ed1d6e0b82e72019550d2547592e 100644
|
| --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
|
| +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
|
| @@ -365,6 +365,11 @@ PnaclCoordinator::PnaclCoordinator(
|
| static_cast<void*>(this), static_cast<void*>(plugin)));
|
| callback_factory_.Initialize(this);
|
| ld_manifest_.reset(new PnaclLDManifest(plugin_->manifest(), manifest_.get()));
|
| + pp::Module *module = pp::Module::Get();
|
| + DCHECK(module);
|
| + nacl_hash_private_interface_ = static_cast<const PPB_NaCl_Hash_Private*>(
|
| + module->GetBrowserInterface(PPB_NACL_HASH_PRIVATE_INTERFACE));
|
| + bitcode_hash_verifier_ = nacl_hash_private_interface_->CreateSHA256Hasher();
|
| }
|
|
|
| PnaclCoordinator::~PnaclCoordinator() {
|
| @@ -379,6 +384,7 @@ PnaclCoordinator::~PnaclCoordinator() {
|
| if (translate_thread_.get() != NULL) {
|
| translate_thread_->AbortSubprocesses();
|
| }
|
| + nacl_hash_private_interface_->Delete(bitcode_hash_verifier_);
|
| }
|
|
|
| void PnaclCoordinator::ReportNonPpapiError(enum PluginErrorCode err_code,
|
| @@ -470,13 +476,20 @@ void PnaclCoordinator::TranslateFinished(int32_t pp_error) {
|
|
|
| if (pnacl_options_.HasCacheKey() && cached_nexe_file_ != NULL) {
|
| // We are using a cache, but had a cache miss, which is why we did the
|
| - // translation. Reset cached_nexe_file_ to have a random name,
|
| - // for scratch purposes, before renaming to the final cache_identity.
|
| - cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(),
|
| - nacl::string(kPnaclTempDir)));
|
| - pp::CompletionCallback cb = callback_factory_.NewCallback(
|
| - &PnaclCoordinator::CachedNexeOpenedForWrite);
|
| - cached_nexe_file_->OpenWrite(cb);
|
| + // translation.
|
| + if (BitcodeHashMatchesContents()) {
|
| + // Reset cached_nexe_file_ to have a random name, for scratch purposes,
|
| + // before renaming to the final cache_identity.
|
| + cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(),
|
| + nacl::string(kPnaclTempDir)));
|
| + pp::CompletionCallback cb = callback_factory_.NewCallback(
|
| + &PnaclCoordinator::CachedNexeOpenedForWrite);
|
| + cached_nexe_file_->OpenWrite(cb);
|
| + } else {
|
| + ReportNonPpapiError(
|
| + ERROR_PNACL_CACHE_HASH_MISMATCH,
|
| + "Bitcode hash does not match bitcode contents.");
|
| + }
|
| } else {
|
| // For now, tolerate bitcode that is missing a cache identity, and
|
| // tolerate the lack of caching in incognito mode.
|
| @@ -485,6 +498,31 @@ void PnaclCoordinator::TranslateFinished(int32_t pp_error) {
|
| }
|
| }
|
|
|
| +bool PnaclCoordinator::BitcodeHashMatchesContents() {
|
| + const nacl::string& expected_hash = pnacl_options_.GetBitcodeHash();
|
| + nacl::string actual_hash;
|
| + uint8_t hash_digest[32];
|
| + nacl_hash_private_interface_->Finish(bitcode_hash_verifier_,
|
| + &hash_digest,
|
| + sizeof hash_digest);
|
| + // Convert 32-byte binary digest to 64-byte hex digest for comparison.
|
| + for (size_t i = 0; i < sizeof hash_digest; i+=8) {
|
| + char buf[17]; // do 16 chars + a null byte at a time.
|
| + SNPRINTF(buf, sizeof buf, "%02x%02x%02x%02x%02x%02x%02x%02x",
|
| + hash_digest[i ], hash_digest[i+1],
|
| + hash_digest[i+2], hash_digest[i+3],
|
| + hash_digest[i+4], hash_digest[i+5],
|
| + hash_digest[i+6], hash_digest[i+7]);
|
| + actual_hash.append(buf);
|
| + }
|
| + if (expected_hash.size() != actual_hash.size()) {
|
| + return false;
|
| + }
|
| + return nacl_hash_private_interface_->SecureMemEqual(expected_hash.c_str(),
|
| + actual_hash.c_str(),
|
| + expected_hash.size());
|
| +}
|
| +
|
| void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) {
|
| if (pp_error != PP_OK) {
|
| if (pp_error == PP_ERROR_NOACCESS) {
|
| @@ -910,11 +948,17 @@ void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error,
|
| PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%"
|
| NACL_PRId32", data=%p)\n", pp_error, data ? &(*data)[0] : 0));
|
| DCHECK(translate_thread_.get());
|
| - translate_thread_->PutBytes(data, pp_error);
|
| // If pp_error > 0, then it represents the number of bytes received.
|
| - if (data && pp_error > 0) {
|
| + if (pp_error > 0) {
|
| pexe_size_ += pp_error;
|
| + // Update hash for verification before data is taken by PutBytes.
|
| + if (pnacl_options_.HasCacheKey()) {
|
| + nacl_hash_private_interface_->Update(bitcode_hash_verifier_,
|
| + &(*data)[0],
|
| + pp_error);
|
| + }
|
| }
|
| + translate_thread_->PutBytes(data, pp_error);
|
| }
|
|
|
| StreamCallback PnaclCoordinator::GetCallback() {
|
|
|