Skip to content

Commit

Permalink
Move CUP to new component client_update_protocol
Browse files Browse the repository at this point in the history
This is in aid of reusing this code to obtain secure time.

BUG=589700

Review URL: https://codereview.chromium.org/1805263002

Cr-Commit-Position: refs/heads/master@{#381836}
  • Loading branch information
mab authored and Commit bot committed Mar 17, 2016
1 parent 9845d25 commit bb61b52
Show file tree
Hide file tree
Showing 15 changed files with 138 additions and 64 deletions.
1 change: 1 addition & 0 deletions components/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ test("components_unittests") {
"//base/test:test_support",
"//components/bookmarks/browser:unit_tests",
"//components/bookmarks/managed:unit_tests",
"//components/client_update_protocol:unit_tests",
"//components/content_settings/core/browser:unit_tests",
"//components/content_settings/core/common",
"//components/content_settings/core/common:unit_tests",
Expand Down
41 changes: 41 additions & 0 deletions components/client_update_protocol.gypi
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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.

{
'targets': [
{
# GN version: //components/client_update_protocol
'target_name': 'client_update_protocol',
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
'../crypto/crypto.gyp:crypto',
],

'include_dirs': [
'..',
],
'sources': [
'client_update_protocol/ecdsa.h',
'client_update_protocol/ecdsa.cc',
],
},
{
# GN version: //components/client_update_protocol:test_support
'target_name': 'client_update_protocol_test_support',
'type': 'static_library',
'dependencies': [
'update_client',
'../testing/gtest.gyp:gtest',
],

'include_dirs': [
'..',
],
'sources': [
'client_update_protocol/ecdsa_unittest.cc',
],
},
],
}
29 changes: 29 additions & 0 deletions components/client_update_protocol/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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.

source_set("client_update_protocol") {
sources = [
"ecdsa.cc",
"ecdsa.h",
]

deps = [
"//base",
"//crypto",
]
}

source_set("unit_tests") {
testonly = true
sources = [
"ecdsa_unittest.cc",
]

deps = [
":client_update_protocol",
"//base",
"//crypto",
"//testing/gtest",
]
}
3 changes: 3 additions & 0 deletions components/client_update_protocol/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_rules = [
"+crypto",
]
3 changes: 3 additions & 0 deletions components/client_update_protocol/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
asargent@chromium.org
sorin@chromium.org
waffles@chromium.org
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/update_client/client_update_protocol_ecdsa.h"
#include "components/client_update_protocol/ecdsa.h"

#include "base/logging.h"
#include "base/macros.h"
Expand All @@ -15,7 +15,7 @@
#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"

namespace update_client {
namespace client_update_protocol {

namespace {

Expand Down Expand Up @@ -84,27 +84,22 @@ bool ParseETagHeader(const base::StringPiece& etag_header_value_in,

} // namespace

ClientUpdateProtocolEcdsa::ClientUpdateProtocolEcdsa(
int key_version,
const base::StringPiece& public_key)
Ecdsa::Ecdsa(int key_version, const base::StringPiece& public_key)
: pub_key_version_(key_version),
public_key_(public_key.begin(), public_key.end()) {}

ClientUpdateProtocolEcdsa::~ClientUpdateProtocolEcdsa() {}
Ecdsa::~Ecdsa() {}

scoped_ptr<ClientUpdateProtocolEcdsa> ClientUpdateProtocolEcdsa::Create(
int key_version,
const base::StringPiece& public_key) {
scoped_ptr<Ecdsa> Ecdsa::Create(int key_version,
const base::StringPiece& public_key) {
DCHECK_GT(key_version, 0);
DCHECK(!public_key.empty());

return make_scoped_ptr(
new ClientUpdateProtocolEcdsa(key_version, public_key));
return make_scoped_ptr(new Ecdsa(key_version, public_key));
}

void ClientUpdateProtocolEcdsa::SignRequest(
const base::StringPiece& request_body,
std::string* query_params) {
void Ecdsa::SignRequest(const base::StringPiece& request_body,
std::string* query_params) {
DCHECK(!request_body.empty());
DCHECK(query_params);

Expand All @@ -126,9 +121,8 @@ void ClientUpdateProtocolEcdsa::SignRequest(
request_hash_hex.c_str());
}

bool ClientUpdateProtocolEcdsa::ValidateResponse(
const base::StringPiece& response_body,
const base::StringPiece& server_etag) {
bool Ecdsa::ValidateResponse(const base::StringPiece& response_body,
const base::StringPiece& server_etag) {
DCHECK(!request_hash_.empty());
DCHECK(!request_query_cup2key_.empty());

Expand Down Expand Up @@ -190,4 +184,4 @@ bool ClientUpdateProtocolEcdsa::ValidateResponse(
return verifier.VerifyFinal();
}

} // namespace update_client
} // namespace client_update_protocol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_UPDATE_CLIENT_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
#define COMPONENTS_UPDATE_CLIENT_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
#ifndef COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
#define COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_

#include <stdint.h>

Expand All @@ -13,57 +13,55 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"

namespace update_client {
namespace client_update_protocol {

// Client Update Protocol v2, or CUP-ECDSA, is used by Google Update (Omaha)
// servers to ensure freshness and authenticity of update checks over HTTP,
// without the overhead of HTTPS -- namely, no PKI, no guarantee of privacy,
// and no request replay protection (since update checks are idempotent).
// servers to ensure freshness and authenticity of server responses over HTTP,
// without the overhead of HTTPS -- namely, no PKI, no guarantee of privacy, and
// no request replay protection.
//
// CUP-ECDSA relies on a single signing operation using ECDSA with SHA-256,
// instead of the original CUP which used HMAC-SHA1 with a random signing key
// encrypted using RSA.
//
// Each ClientUpdateProtocolEcdsa object represents a single update check in
// flight -- a call to SignRequest() generates internal state that will be used
// by ValidateResponse().
class ClientUpdateProtocolEcdsa {
// Each |Ecdsa| object represents a single network ping in flight -- a call to
// SignRequest() generates internal state that will be used by
// ValidateResponse().
class Ecdsa {
public:
~ClientUpdateProtocolEcdsa();
~Ecdsa();

// Initializes this instance of CUP-ECDSA with a versioned public key.
// |key_version| must be non-negative. |public_key| is expected to be a
// DER-encoded ASN.1 SubjectPublicKeyInfo containing an ECDSA public key.
// Returns a NULL pointer on failure.
static scoped_ptr<ClientUpdateProtocolEcdsa> Create(
int key_version,
const base::StringPiece& public_key);

// Generates freshness/authentication data for an outgoing update check.
// |request_body| contains the body of the update check request in UTF-8.
// On return, |query_params| contains a set of query parameters (in UTF-8)
// to be appended to the URL.
static scoped_ptr<Ecdsa> Create(int key_version,
const base::StringPiece& public_key);

// Generates freshness/authentication data for an outgoing ping.
// |request_body| contains the body of the ping in UTF-8. On return,
// |query_params| contains a set of query parameters (in UTF-8) to be appended
// to the URL.
//
// This method will store internal state in this instance used by calls to
// ValidateResponse(); if you need to have multiple update checks in flight,
// ValidateResponse(); if you need to have multiple pings in flight,
// initialize a separate CUP-ECDSA instance for each one.
void SignRequest(const base::StringPiece& request_body,
std::string* query_params);

// Validates a response given to a update check request previously signed
// with SignRequest(). |response_body| contains the body of the response in
// Validates a response given to a ping previously signed with
// SignRequest(). |response_body| contains the body of the response in
// UTF-8. |server_proof| contains the ECDSA signature and observed request
// hash, which is passed in the ETag HTTP header. Returns true if the
// response is valid and the observed request hash matches the sent hash.
// This method uses internal state that is set by a prior SignRequest() call.
// hash, which is passed in the ETag HTTP header. Returns true if the response
// is valid and the observed request hash matches the sent hash. This method
// uses internal state that is set by a prior SignRequest() call.
bool ValidateResponse(const base::StringPiece& response_body,
const base::StringPiece& server_etag);

private:
friend class CupEcdsaTest;

ClientUpdateProtocolEcdsa(int key_version,
const base::StringPiece& public_key);
Ecdsa(int key_version, const base::StringPiece& public_key);

// The server keeps multiple signing keys; a version must be sent so that
// the correct signing key is used to sign the assembled message.
Expand All @@ -80,9 +78,9 @@ class ClientUpdateProtocolEcdsa {
// modified on each call to SignRequest(), and checked by ValidateResponse().
std::string request_query_cup2key_;

DISALLOW_IMPLICIT_CONSTRUCTORS(ClientUpdateProtocolEcdsa);
DISALLOW_IMPLICIT_CONSTRUCTORS(Ecdsa);
};

} // namespace update_client
} // namespace client_update_protocol

#endif // COMPONENTS_UPDATE_CLIENT_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
#endif // COMPONENTS_CLIENT_UPDATE_PROTOCOL_ECDSA_H_
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "components/update_client/client_update_protocol_ecdsa.h"
#include "components/client_update_protocol/ecdsa.h"
#include "crypto/random.h"
#include "crypto/secure_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace update_client {
namespace client_update_protocol {

namespace {

Expand All @@ -41,7 +41,7 @@ std::string GetPublicKeyForTesting() {
class CupEcdsaTest : public testing::Test {
protected:
void SetUp() override {
cup_ = ClientUpdateProtocolEcdsa::Create(8, GetPublicKeyForTesting());
cup_ = Ecdsa::Create(8, GetPublicKeyForTesting());
ASSERT_TRUE(cup_.get());
}

Expand All @@ -50,10 +50,10 @@ class CupEcdsaTest : public testing::Test {
base::StringPrintf("%d:%u", cup_->pub_key_version_, nonce);
}

ClientUpdateProtocolEcdsa& CUP() { return *cup_.get(); }
Ecdsa& CUP() { return *cup_.get(); }

private:
scoped_ptr<ClientUpdateProtocolEcdsa> cup_;
scoped_ptr<Ecdsa> cup_;
};

TEST_F(CupEcdsaTest, SignRequest) {
Expand Down Expand Up @@ -295,4 +295,4 @@ TEST_F(CupEcdsaTest, ValidateResponse_TestSigning) {
":2727bc2b3c33feb6800a830f4055901dd87d65a84184c5fbeb3f816db0a243f5"));
}

} // namespace update_client
} // namespace client_update_protocol
1 change: 1 addition & 0 deletions components/components.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
'bubble.gypi',
'captive_portal.gypi',
'certificate_reporting.gypi',
'client_update_protocol.gypi',
'cloud_devices.gypi',
'component_updater.gypi',
'content_settings.gypi',
Expand Down
5 changes: 4 additions & 1 deletion components/components_tests.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
'child_trace_message_filter_unittest_sources': [
'tracing/child_trace_message_filter_unittest.cc',
],
'client_update_protocol_unittest_sources': [
'client_update_protocol/ecdsa_unittest.cc',
],
'cloud_devices_unittest_sources': [
'cloud_devices/common/cloud_devices_urls_unittest.cc',
'cloud_devices/common/printer_description_unittest.cc',
Expand Down Expand Up @@ -811,7 +814,6 @@
],
'update_client_unittest_sources': [
'update_client/component_patcher_unittest.cc',
'update_client/client_update_protocol_ecdsa_unittest.cc',
'update_client/crx_downloader_unittest.cc',
'update_client/ping_manager_unittest.cc',
'update_client/request_sender_unittest.cc',
Expand Down Expand Up @@ -945,6 +947,7 @@
'<@(bubble_unittest_sources)',
'<@(captive_portal_unittest_sources)',
'<@(certificate_reporting_unittest_sources)',
'<@(client_update_protocol_unittest_sources)',
'<@(cloud_devices_unittest_sources)',
'<@(component_updater_unittest_sources)',
'<@(content_settings_unittest_sources)',
Expand Down
3 changes: 1 addition & 2 deletions components/update_client.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
'../third_party/zlib/google/zip.gyp:zip',
'../net/net.gyp:net',
'../url/url.gyp:url_lib',
'client_update_protocol',
'crx_file',
],

Expand All @@ -33,8 +34,6 @@
'update_client/action_wait.h',
'update_client/background_downloader_win.cc',
'update_client/background_downloader_win.h',
'update_client/client_update_protocol_ecdsa.cc',
'update_client/client_update_protocol_ecdsa.h',
'update_client/component_patcher.cc',
'update_client/component_patcher.h',
'update_client/component_patcher_operation.cc',
Expand Down
4 changes: 1 addition & 3 deletions components/update_client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ source_set("update_client") {
"action_wait.h",
"background_downloader_win.cc",
"background_downloader_win.h",
"client_update_protocol_ecdsa.cc",
"client_update_protocol_ecdsa.h",
"component_patcher.cc",
"component_patcher.h",
"component_patcher_operation.cc",
Expand Down Expand Up @@ -54,6 +52,7 @@ source_set("update_client") {

deps = [
"//base",
"//components/client_update_protocol",
"//components/crx_file",
"//courgette:courgette_lib",
"//crypto",
Expand Down Expand Up @@ -90,7 +89,6 @@ source_set("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
"client_update_protocol_ecdsa_unittest.cc",
"component_patcher_unittest.cc",
"crx_downloader_unittest.cc",
"ping_manager_unittest.cc",
Expand Down
1 change: 1 addition & 0 deletions components/update_client/DEPS
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include_rules = [
"+components/client_update_protocol",
"+components/crx_file",
"+courgette",
"+crypto",
Expand Down
Loading

0 comments on commit bb61b52

Please sign in to comment.