Skip to content

Commit

Permalink
Allow the component updater framework to control Origin Trials.
Browse files Browse the repository at this point in the history
This patch adds support for updating the public key for verifying origin trial token signatures through the component updater. Future patches are planned to add support for disabling individual experimental APIs and for revoking individual trial tokens. This patch lays the groundwork for these, but does not actually provide those extra features.

The component is not required to be present in order for origin trials to work (the default key will be used in that case), but if it is, it should include the public key in its manifest as a base64-encoded string representing 32 bytes, like this:

	"origin-trials": {
		"public-key": "abcdefghjijklmnopqrstuvwxabcdefghjijklmnopq="
	}

BUG=603588

Review-Url: https://codereview.chromium.org/1887743003
Cr-Commit-Position: refs/heads/master@{#390636}
  • Loading branch information
clelland authored and Commit bot committed Apr 29, 2016
1 parent 8f5fa2a commit 99c766f
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 0 deletions.
2 changes: 2 additions & 0 deletions chrome/browser/chrome_browser_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "chrome/browser/chrome_browser_main_extra_parts.h"
#include "chrome/browser/component_updater/cld_component_installer.h"
#include "chrome/browser/component_updater/ev_whitelist_component_installer.h"
#include "chrome/browser/component_updater/origin_trials_component_installer.h"
#include "chrome/browser/component_updater/pepper_flash_component_installer.h"
#include "chrome/browser/component_updater/recovery_component_installer.h"
#include "chrome/browser/component_updater/sth_set_component_installer.h"
Expand Down Expand Up @@ -495,6 +496,7 @@ void RegisterComponentsForUpdate() {
// Chrome OS: On Chrome OS this registration is delayed until user login.
RegisterSTHSetComponent(cus, path);
#endif // defined(OS_ANDROID)
RegisterOriginTrialsComponent(cus, path);
}

#if defined(OS_WIN)
Expand Down
108 changes: 108 additions & 0 deletions chrome/browser/component_updater/origin_trials_component_installer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2016 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 "chrome/browser/component_updater/origin_trials_component_installer.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "chrome/common/chrome_switches.h"
#include "components/component_updater/component_updater_paths.h"

// The client-side configuration for the origin trial framework can be
// overridden by an installed component named 'OriginTrials' (extension id
// kfoklmclfodeliojeaekpoflbkkhojea. This component currently consists of just a
// manifest.json file, which can contain a custom key named 'origin-trials'. The
// value of this key is a dictionary:
//
// {
// "public-key": "<base64-encoding of replacement public key>",
// "disabled-features": [<list of features to disable>],
// "revoked-tokens": "<base64-encoded data>"
// }
//
// TODO(iclelland): Implement support for revoked tokens and disabled features.
//
// If the component is not present in the user data directory, the default
// configuration will be used.

namespace component_updater {

namespace {

// Extension id is kfoklmclfodeliojeaekpoflbkkhojea
const uint8_t kSha256Hash[] = {0xa5, 0xea, 0xbc, 0x2b, 0x5e, 0x34, 0xb8, 0xe9,
0x40, 0x4a, 0xfe, 0x5b, 0x1a, 0xa7, 0xe9, 0x40,
0xa8, 0xc5, 0xef, 0xa1, 0x9e, 0x20, 0x5a, 0x39,
0x73, 0x98, 0x98, 0x0f, 0x7a, 0x76, 0x62, 0xfa};

} // namespace

bool OriginTrialsComponentInstallerTraits::VerifyInstallation(
const base::DictionaryValue& manifest,
const base::FilePath& install_dir) const {
// Test if the "origin-trials" key is present in the manifest.
return manifest.HasKey("origin-trials");
}

bool OriginTrialsComponentInstallerTraits::CanAutoUpdate() const {
return true;
}

bool OriginTrialsComponentInstallerTraits::RequiresNetworkEncryption() const {
return true;
}

bool OriginTrialsComponentInstallerTraits::OnCustomInstall(
const base::DictionaryValue& manifest,
const base::FilePath& install_dir) {
return true;
}

void OriginTrialsComponentInstallerTraits::ComponentReady(
const base::Version& version,
const base::FilePath& install_dir,
std::unique_ptr<base::DictionaryValue> manifest) {
// Read the public key from the manifest and set the command line.
std::string override_public_key;
if (manifest->GetString("origin-trials.public-key", &override_public_key)) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(switches::kOriginTrialPublicKey,
override_public_key);
}
}

base::FilePath OriginTrialsComponentInstallerTraits::GetBaseDirectory() const {
base::FilePath result;
PathService::Get(DIR_ORIGIN_TRIAL_KEYS, &result);
return result;
}

void OriginTrialsComponentInstallerTraits::GetHash(
std::vector<uint8_t>* hash) const {
if (!hash)
return;
hash->assign(kSha256Hash, kSha256Hash + arraysize(kSha256Hash));
}

std::string OriginTrialsComponentInstallerTraits::GetName() const {
return "Origin Trials";
}

std::string OriginTrialsComponentInstallerTraits::GetAp() const {
return std::string();
}

void RegisterOriginTrialsComponent(ComponentUpdateService* cus,
const base::FilePath& user_data_dir) {
std::unique_ptr<ComponentInstallerTraits> traits(
new OriginTrialsComponentInstallerTraits());
// |cus| will take ownership of |installer| during installer->Register(cus).
DefaultComponentInstaller* installer =
new DefaultComponentInstaller(std::move(traits));
installer->Register(cus, base::Closure());
}

} // namespace component_updater
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2016 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 CHROME_BROWSER_COMPONENT_UPDATER_ORIGIN_TRIALS_COMPONENT_INSTALLER_H_
#define CHROME_BROWSER_COMPONENT_UPDATER_ORIGIN_TRIALS_COMPONENT_INSTALLER_H_

#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/values.h"
#include "base/version.h"
#include "components/component_updater/default_component_installer.h"

namespace component_updater {

class ComponentUpdateService;

class OriginTrialsComponentInstallerTraits : public ComponentInstallerTraits {
public:
OriginTrialsComponentInstallerTraits() = default;
~OriginTrialsComponentInstallerTraits() override = default;

private:
bool VerifyInstallation(const base::DictionaryValue& manifest,
const base::FilePath& install_dir) const override;
bool CanAutoUpdate() const override;
bool RequiresNetworkEncryption() const override;
bool OnCustomInstall(const base::DictionaryValue& manifest,
const base::FilePath& install_dir) override;
void ComponentReady(const base::Version& version,
const base::FilePath& install_dir,
std::unique_ptr<base::DictionaryValue> manifest) override;
base::FilePath GetBaseDirectory() const override;
void GetHash(std::vector<uint8_t>* hash) const override;
std::string GetName() const override;
std::string GetAp() const override;

DISALLOW_COPY_AND_ASSIGN(OriginTrialsComponentInstallerTraits);
};

// Call once during startup to make the component update service aware of
// the origin trials update component.
void RegisterOriginTrialsComponent(ComponentUpdateService* cus,
const base::FilePath& user_data_dir);

} // namespace component_updater

#endif // CHROME_BROWSER_COMPONENT_UPDATER_ORIGIN_TRIALS_COMPONENT_INSTALLER_H_
2 changes: 2 additions & 0 deletions chrome/chrome_browser.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@
'browser/component_updater/component_updater_resource_throttle.h',
'browser/component_updater/ev_whitelist_component_installer.cc',
'browser/component_updater/ev_whitelist_component_installer.h',
'browser/component_updater/origin_trials_component_installer.cc',
'browser/component_updater/origin_trials_component_installer.h',
'browser/component_updater/pnacl_component_installer.cc',
'browser/component_updater/pnacl_component_installer.h',
'browser/component_updater/recovery_component_installer.cc',
Expand Down
3 changes: 3 additions & 0 deletions components/component_updater/component_updater_paths.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ bool PathProvider(int key, base::FilePath* result) {
case DIR_CERT_TRANS_TREE_STATES:
cur = cur.Append(FILE_PATH_LITERAL("CertificateTransparency"));
break;
case DIR_ORIGIN_TRIAL_KEYS:
cur = cur.Append(FILE_PATH_LITERAL("OriginTrials"));
break;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions components/component_updater/component_updater_paths.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ enum {
DIR_COMPONENT_EV_WHITELIST, // EV whitelist for CT files.
DIR_SUPERVISED_USER_WHITELISTS, // Supervised user whitelists.
DIR_CERT_TRANS_TREE_STATES, // Signed Tree Heads for CT logs.
DIR_ORIGIN_TRIAL_KEYS, // Public keys and revoked tokens for origin
// trials.
PATH_END
};

Expand Down

0 comments on commit 99c766f

Please sign in to comment.