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

Unified Diff: components/policy/core/common/cloud/cloud_policy_validator.cc

Issue 116273002: Added support for signed policy blobs on desktop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix for ios. Created 6 years, 11 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
Index: components/policy/core/common/cloud/cloud_policy_validator.cc
diff --git a/components/policy/core/common/cloud/cloud_policy_validator.cc b/components/policy/core/common/cloud/cloud_policy_validator.cc
index 5bbc6bc7c99f468ecc7423f7ab058b1b068c9623..f85561dc675a38ea16ae1b681f7bbfc51dfced4d 100644
--- a/components/policy/core/common/cloud/cloud_policy_validator.cc
+++ b/components/policy/core/common/cloud/cloud_policy_validator.cc
@@ -6,6 +6,7 @@
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
@@ -28,6 +29,23 @@ const uint8 kSignatureAlgorithm[] = {
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
};
+const char kMetricPolicyKeyVerification[] = "Enterprise.PolicyKeyVerification";
+
+enum MetricPolicyKeyVerification {
+ // UMA metric recorded when the client has no verification key.
+ METRIC_POLICY_KEY_VERIFICATION_KEY_MISSING,
+ // Recorded when the policy being verified has no key signature (e.g. policy
+ // fetched before the server supported the verification key).
+ METRIC_POLICY_KEY_VERIFICATION_SIGNATURE_MISSING,
+ // Recorded when the key signature did not match the expected value (in
+ // theory, this should only happen after key rotation or if the policy cached
+ // on disk has been modified).
+ METRIC_POLICY_KEY_VERIFICATION_FAILED,
+ // Recorded when key verification succeeded.
+ METRIC_POLICY_KEY_VERIFICATION_SUCCEEDED,
+ METRIC_POLICY_KEY_VERIFICATION_SIZE // Must be the last.
+};
+
} // namespace
CloudPolicyValidatorBase::~CloudPolicyValidatorBase() {}
@@ -83,16 +101,22 @@ void CloudPolicyValidatorBase::ValidatePayload() {
validation_flags_ |= VALIDATE_PAYLOAD;
}
-void CloudPolicyValidatorBase::ValidateSignature(const std::vector<uint8>& key,
- bool allow_key_rotation) {
+void CloudPolicyValidatorBase::ValidateSignature(
+ const std::string& key,
+ const std::string& verification_key,
+ const std::string& key_signature,
+ bool allow_key_rotation) {
validation_flags_ |= VALIDATE_SIGNATURE;
- key_ = std::string(reinterpret_cast<const char*>(vector_as_array(&key)),
- key.size());
+ set_verification_key(verification_key);
+ key_ = key;
+ key_signature_ = key_signature;
allow_key_rotation_ = allow_key_rotation;
}
-void CloudPolicyValidatorBase::ValidateInitialKey() {
+void CloudPolicyValidatorBase::ValidateInitialKey(
+ const std::string& verification_key) {
validation_flags_ |= VALIDATE_INITIAL_KEY;
+ set_verification_key(verification_key);
}
void CloudPolicyValidatorBase::ValidateAgainstCurrentPolicy(
@@ -210,6 +234,65 @@ void CloudPolicyValidatorBase::RunChecks() {
}
}
+// Verifies the |new_public_key_verification_signature| for the |new_public_key|
+// in the policy blob.
+bool CloudPolicyValidatorBase::CheckNewPublicKeyVerificationSignature() {
+ // If there's no local verification key, then just return true (no
+ // validation possible).
+ if (verification_key_.empty()) {
+ UMA_HISTOGRAM_ENUMERATION(kMetricPolicyKeyVerification,
+ METRIC_POLICY_KEY_VERIFICATION_KEY_MISSING,
+ METRIC_POLICY_KEY_VERIFICATION_SIZE);
+ return true;
+ }
+
+ if (!policy_->has_new_public_key_verification_signature()) {
+ // Policy does not contain a verification signature, so log an error.
+ LOG(ERROR) << "Policy is missing public_key_verification_signature";
+ UMA_HISTOGRAM_ENUMERATION(kMetricPolicyKeyVerification,
+ METRIC_POLICY_KEY_VERIFICATION_SIGNATURE_MISSING,
+ METRIC_POLICY_KEY_VERIFICATION_SIZE);
+ // TODO(atwilson): Return an error on failed signature verification once
+ // our test servers and unittests are returning policy with a verification
+ // signature (http://crbug.com/275291).
+ return true;
+ }
+
+ if (!CheckVerificationKeySignature(
+ policy_->new_public_key(),
+ verification_key_,
+ policy_->new_public_key_verification_signature())) {
+ LOG(ERROR) << "Signature verification failed";
+ UMA_HISTOGRAM_ENUMERATION(kMetricPolicyKeyVerification,
+ METRIC_POLICY_KEY_VERIFICATION_FAILED,
+ METRIC_POLICY_KEY_VERIFICATION_SIZE);
+ // TODO(atwilson): Update this code to include the domain name in the
+ // signature, and return an error once the server starts returning this.
+ return true;
+ }
+ // Signature verification succeeded - return success to the caller.
+ UMA_HISTOGRAM_ENUMERATION(kMetricPolicyKeyVerification,
+ METRIC_POLICY_KEY_VERIFICATION_SUCCEEDED,
+ METRIC_POLICY_KEY_VERIFICATION_SIZE);
+ return true;
+}
+
+bool CloudPolicyValidatorBase::CheckVerificationKeySignature(
+ const std::string& key,
+ const std::string& verification_key,
+ const std::string& signature) {
+ // TODO(atwilson): Update this routine to include the domain name in the
+ // signed data.
+ return VerifySignature(key, verification_key, signature);
+}
+
+void CloudPolicyValidatorBase::set_verification_key(
+ const std::string& verification_key) {
+ // Make sure we aren't overwriting the verification key with a different key.
+ DCHECK(verification_key_.empty() || verification_key_ == verification_key);
+ verification_key_ = verification_key;
+}
+
CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckSignature() {
const std::string* signature_key = &key_;
if (policy_->has_new_public_key() && allow_key_rotation_) {
@@ -217,9 +300,14 @@ CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckSignature() {
if (!policy_->has_new_public_key_signature() ||
!VerifySignature(policy_->new_public_key(), key_,
policy_->new_public_key_signature())) {
- LOG(ERROR) << "New public key signature verification failed";
+ LOG(ERROR) << "New public key rotation signature verification failed";
return VALIDATION_BAD_SIGNATURE;
}
+
+ if (!CheckNewPublicKeyVerificationSignature()) {
+ LOG(ERROR) << "New public key root verification failed";
+ return VALIDATION_BAD_KEY_VERIFICATION_SIGNATURE;
+ }
}
if (!policy_->has_policy_data_signature() ||
@@ -229,6 +317,16 @@ CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckSignature() {
return VALIDATION_BAD_SIGNATURE;
}
+ // If a key verification signature is available, then verify the base signing
+ // key as well.
+ if (!key_signature_.empty() &&
+ !CheckVerificationKeySignature(key_, verification_key_, key_signature_)) {
Mattias Nissler (ping if slow) 2014/01/31 21:00:35 Wouldn't we fail here for the case where the verif
Andrew T Wilson (Slow) 2014/02/02 11:31:58 When we do key rotation, we'll need to add code on
+ LOG(ERROR) << "Verification key signature verification failed";
+ // TODO(atwilson): Update to return an error once the server is properly
+ // generating a verification signature (http://crbug.com/275291).
+ // return VALIDATION_BAD_KEY_VERIFICATION_SIGNATURE;
+ }
+
return VALIDATION_OK;
}
@@ -241,6 +339,10 @@ CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckInitialKey() {
return VALIDATION_BAD_INITIAL_SIGNATURE;
}
+ if (!CheckNewPublicKeyVerificationSignature()) {
+ LOG(ERROR) << "Initial policy root signature validation failed";
+ return VALIDATION_BAD_KEY_VERIFICATION_SIGNATURE;
+ }
return VALIDATION_OK;
}

Powered by Google App Engine
This is Rietveld 408576698