summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortengs <tengs@chromium.org>2015-04-06 19:53:48 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-07 02:54:12 +0000
commitbbb566c2518db4a962f5ca529bb8204ec53f94c1 (patch)
tree95661345e7d39a3e28cbc050666a477e61fbd21f
parent69fc8e7fe0f3025afb513fce0f5eed95d40778fb (diff)
downloadchromium_src-bbb566c2518db4a962f5ca529bb8204ec53f94c1.zip
chromium_src-bbb566c2518db4a962f5ca529bb8204ec53f94c1.tar.gz
chromium_src-bbb566c2518db4a962f5ca529bb8204ec53f94c1.tar.bz2
Add SecureMessage definitions to CryptAuth.
BUG=473471 Review URL: https://codereview.chromium.org/1060483002 Cr-Commit-Position: refs/heads/master@{#324006}
-rw-r--r--components/components_tests.gyp2
-rw-r--r--components/proximity_auth.gypi21
-rw-r--r--components/proximity_auth/cryptauth/BUILD.gn20
-rw-r--r--components/proximity_auth/cryptauth/fake_secure_message_delegate.cc192
-rw-r--r--components/proximity_auth/cryptauth/fake_secure_message_delegate.h51
-rw-r--r--components/proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc196
-rw-r--r--components/proximity_auth/cryptauth/proto/BUILD.gn1
-rw-r--r--components/proximity_auth/cryptauth/proto/securemessage.proto95
-rw-r--r--components/proximity_auth/cryptauth/secure_message_delegate.cc27
-rw-r--r--components/proximity_auth/cryptauth/secure_message_delegate.h101
10 files changed, 706 insertions, 0 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 46fa9b5..99e0772 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -397,6 +397,7 @@
'proximity_auth/cryptauth/cryptauth_account_token_fetcher_unittest.cc',
'proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc',
'proximity_auth/cryptauth/cryptauth_client_unittest.cc',
+ 'proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc',
'proximity_auth/proximity_auth_system_unittest.cc',
'proximity_auth/remote_status_update_unittest.cc',
'proximity_auth/wire_message_unittest.cc',
@@ -931,6 +932,7 @@
'components.gyp:copresence',
'components.gyp:copresence_test_support',
'components.gyp:cryptauth',
+ 'components.gyp:cryptauth_test_support',
'components.gyp:feedback_component',
'components.gyp:proximity_auth',
],
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi
index b5e3c03..1541ddb 100644
--- a/components/proximity_auth.gypi
+++ b/components/proximity_auth.gypi
@@ -50,6 +50,7 @@
'type': 'static_library',
'sources': [
'proximity_auth/cryptauth/proto/cryptauth_api.proto',
+ 'proximity_auth/cryptauth/proto/securemessage.proto',
],
'variables': {
'proto_in_dir': 'proximity_auth/cryptauth/proto',
@@ -81,6 +82,26 @@
"proximity_auth/cryptauth/cryptauth_client_factory.h",
"proximity_auth/cryptauth/cryptauth_enrollment_utils.cc",
"proximity_auth/cryptauth/cryptauth_enrollment_utils.h",
+ "proximity_auth/cryptauth/secure_message_delegate.cc",
+ "proximity_auth/cryptauth/secure_message_delegate.h",
+ ],
+ 'export_dependent_settings': [
+ 'cryptauth_proto',
+ ],
+ },
+ {
+ 'target_name': 'cryptauth_test_support',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ 'cryptauth_proto',
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ "proximity_auth/cryptauth/fake_secure_message_delegate.cc",
+ "proximity_auth/cryptauth/fake_secure_message_delegate.h",
],
'export_dependent_settings': [
'cryptauth_proto',
diff --git a/components/proximity_auth/cryptauth/BUILD.gn b/components/proximity_auth/cryptauth/BUILD.gn
index ccf0ac2..e496151 100644
--- a/components/proximity_auth/cryptauth/BUILD.gn
+++ b/components/proximity_auth/cryptauth/BUILD.gn
@@ -15,6 +15,8 @@ source_set("cryptauth") {
"cryptauth_client_factory.h",
"cryptauth_enrollment_utils.cc",
"cryptauth_enrollment_utils.h",
+ "secure_message_delegate.cc",
+ "secure_message_delegate.h",
]
deps = [
@@ -28,16 +30,34 @@ source_set("cryptauth") {
]
}
+source_set("test_support") {
+ sources = [
+ "fake_secure_message_delegate.cc",
+ "fake_secure_message_delegate.h",
+ ]
+
+ deps = [
+ ":cryptauth",
+ "//base",
+ ]
+
+ public_deps = [
+ "proto",
+ ]
+}
+
source_set("unit_tests") {
testonly = true
sources = [
"cryptauth_account_token_fetcher_unittest.cc",
"cryptauth_api_call_flow_unittest.cc",
"cryptauth_client_unittest.cc",
+ "fake_secure_message_delegate_unittest.cc",
]
deps = [
":cryptauth",
+ ":test_support",
"//base/test:test_support",
"//google_apis:test_support",
"//net:test_support",
diff --git a/components/proximity_auth/cryptauth/fake_secure_message_delegate.cc b/components/proximity_auth/cryptauth/fake_secure_message_delegate.cc
new file mode 100644
index 0000000..195c24b
--- /dev/null
+++ b/components/proximity_auth/cryptauth/fake_secure_message_delegate.cc
@@ -0,0 +1,192 @@
+// Copyright 2015 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 "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "base/md5.h"
+#include "base/strings/string_util.h"
+
+namespace proximity_auth {
+
+namespace {
+
+const char kKeyPrefix[] = "fake_key_";
+const char kPrivateKeyPrefix[] = "private_";
+
+// Encrypts the |plaintext| with the |key| using the |encryption_scheme| and
+// returns the ciphertext.
+std::string Encrypt(const std::string& plaintext,
+ const std::string& key,
+ const securemessage::EncScheme& encryption_scheme) {
+ if (encryption_scheme == securemessage::NONE)
+ return plaintext;
+
+ // Encrypt with a Vigenere cipher.
+ std::string ciphertext;
+ ciphertext.resize(plaintext.size());
+ for (size_t i = 0; i < plaintext.size(); ++i) {
+ unsigned char plaintext_char = plaintext[i];
+ unsigned char key_char = key[i % key.size()];
+ ciphertext[i] = plaintext_char + key_char;
+ }
+ return ciphertext;
+}
+
+// Decrypts the |ciphertext| with the |key| using the |encryption_scheme| and
+// returns the plaintext.
+std::string Decrypt(const std::string& ciphertext,
+ const std::string& key,
+ const securemessage::EncScheme& encryption_scheme) {
+ if (encryption_scheme == securemessage::NONE)
+ return ciphertext;
+
+ // Decrypt with a Vigenere cipher.
+ std::string plaintext;
+ plaintext.resize(ciphertext.size());
+ for (size_t i = 0; i < ciphertext.size(); ++i) {
+ unsigned char ciphertext_char = ciphertext[i];
+ unsigned char key_char = key[i % key.size()];
+ plaintext[i] = ciphertext_char - key_char;
+ }
+ return plaintext;
+}
+
+// Signs the |payload| and |associated_data| with the |key| using the
+// |signature_scheme| and returns the signature.
+std::string Sign(const std::string& payload,
+ const std::string& associated_data,
+ const std::string& key) {
+ return base::MD5String(payload + "|" + associated_data + "|" + key);
+}
+
+// Verifies that the |signature| for the the |payload| and |associated_data| is
+// valid for the given the |key| and |signature_scheme|.
+bool Verify(const std::string& signature,
+ const std::string& payload,
+ const std::string& associated_data,
+ const std::string& key,
+ const securemessage::SigScheme& signature_scheme) {
+ std::string signing_key;
+
+ if (signature_scheme == securemessage::HMAC_SHA256) {
+ signing_key = key;
+ } else {
+ std::string prefix = kPrivateKeyPrefix;
+ bool is_private_key = StartsWithASCII(key, prefix, true);
+ signing_key = is_private_key ? key.substr(prefix.size()) : prefix + key;
+ }
+
+ std::string expected_signature = Sign(payload, associated_data, signing_key);
+ return signature == expected_signature;
+}
+
+} // namespace
+
+FakeSecureMessageDelegate::FakeSecureMessageDelegate()
+ : next_public_key_(std::string(kKeyPrefix) + "0") {
+}
+
+FakeSecureMessageDelegate::~FakeSecureMessageDelegate() {
+}
+
+void FakeSecureMessageDelegate::GenerateKeyPair(
+ const GenerateKeyPairCallback& callback) {
+ std::string public_key = next_public_key_;
+
+ // The private key is simply the public key prepended with "private_".
+ std::string private_key(kPrivateKeyPrefix + public_key);
+
+ next_public_key_ = std::string(kKeyPrefix) + base::MD5String(public_key);
+
+ callback.Run(public_key, private_key);
+}
+
+void FakeSecureMessageDelegate::DeriveKey(const std::string& private_key,
+ const std::string& public_key,
+ const DeriveKeyCallback& callback) {
+ // To ensure that the same symmetric key is derived for DeriveKey(private1,
+ // public2) and DeriveKey(private2, public1), we remove the prefix from the
+ // private key so it is equal to its corresponding public key.
+ std::string prefix(kPrivateKeyPrefix);
+ std::string normalized_private_key =
+ StartsWithASCII(private_key, prefix, true)
+ ? private_key.substr(prefix.size())
+ : private_key;
+
+ std::vector<std::string> keys;
+ keys.push_back(normalized_private_key);
+ keys.push_back(public_key);
+ std::sort(keys.begin(), keys.end());
+ callback.Run(base::MD5String(keys[0] + "|" + keys[1]));
+}
+
+void FakeSecureMessageDelegate::CreateSecureMessage(
+ const std::string& payload,
+ const std::string& key,
+ const CreateOptions& create_options,
+ const CreateSecureMessageCallback& callback) {
+ securemessage::Header header;
+ header.set_signature_scheme(create_options.signature_scheme);
+ header.set_encryption_scheme(create_options.encryption_scheme);
+ if (!create_options.public_metadata.empty())
+ header.set_public_metadata(create_options.public_metadata);
+ if (!create_options.verification_key_id.empty())
+ header.set_verification_key_id(create_options.verification_key_id);
+ if (!create_options.decryption_key_id.empty())
+ header.set_decryption_key_id(create_options.decryption_key_id);
+
+ securemessage::HeaderAndBody header_and_body;
+ header_and_body.mutable_header()->CopyFrom(header);
+ header_and_body.set_body(
+ Encrypt(payload, key, create_options.encryption_scheme));
+ std::string serialized_header_and_body;
+ header_and_body.SerializeToString(&serialized_header_and_body);
+
+ securemessage::SecureMessage secure_message;
+ secure_message.set_header_and_body(serialized_header_and_body);
+ secure_message.set_signature(
+ Sign(payload, create_options.associated_data, key));
+
+ std::string serialized_secure_message;
+ secure_message.SerializeToString(&serialized_secure_message);
+ callback.Run(serialized_secure_message);
+}
+
+void FakeSecureMessageDelegate::UnwrapSecureMessage(
+ const std::string& serialized_message,
+ const std::string& key,
+ const UnwrapOptions& unwrap_options,
+ const UnwrapSecureMessageCallback& callback) {
+ securemessage::SecureMessage secure_message;
+ if (!secure_message.ParseFromString(serialized_message)) {
+ LOG(ERROR) << "Failed to parse SecureMessage.";
+ callback.Run(false, std::string(), securemessage::Header());
+ return;
+ }
+
+ securemessage::HeaderAndBody header_and_body;
+ if (!header_and_body.ParseFromString(secure_message.header_and_body())) {
+ LOG(ERROR) << "Failed to parse secure message HeaderAndBody.";
+ callback.Run(false, std::string(), securemessage::Header());
+ return;
+ }
+
+ const securemessage::Header& header = header_and_body.header();
+ std::string payload =
+ Decrypt(header_and_body.body(), key, unwrap_options.encryption_scheme);
+
+ bool verified = Verify(secure_message.signature(), payload,
+ unwrap_options.associated_data, key,
+ unwrap_options.signature_scheme);
+ if (verified) {
+ callback.Run(true, payload, header);
+ } else {
+ callback.Run(false, std::string(), securemessage::Header());
+ }
+}
+
+} // namespace proximity_auth
diff --git a/components/proximity_auth/cryptauth/fake_secure_message_delegate.h b/components/proximity_auth/cryptauth/fake_secure_message_delegate.h
new file mode 100644
index 0000000..ad8b21b
--- /dev/null
+++ b/components/proximity_auth/cryptauth/fake_secure_message_delegate.h
@@ -0,0 +1,51 @@
+// Copyright 2015 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 COMPONENTS_PROXIMITY_AUTH_FAKE_SECURE_MESSAGE_DELEGATE_H
+#define COMPONENTS_PROXIMITY_AUTH_FAKE_SECURE_MESSAGE_DELEGATE_H
+
+#include "base/macros.h"
+#include "components/proximity_auth/cryptauth/secure_message_delegate.h"
+
+namespace proximity_auth {
+
+// Fake implementation of SecureMessageDelegate used in tests.
+// For clarity in tests, all functions in this delegate will invoke their
+// callback with the result before returning.
+class FakeSecureMessageDelegate : public SecureMessageDelegate {
+ public:
+ FakeSecureMessageDelegate();
+ ~FakeSecureMessageDelegate() override;
+
+ // SecureMessageDelegate:
+ void GenerateKeyPair(const GenerateKeyPairCallback& callback) override;
+ void DeriveKey(const std::string& private_key,
+ const std::string& public_key,
+ const DeriveKeyCallback& callback) override;
+ void CreateSecureMessage(
+ const std::string& payload,
+ const std::string& key,
+ const CreateOptions& create_options,
+ const CreateSecureMessageCallback& callback) override;
+ void UnwrapSecureMessage(
+ const std::string& serialized_message,
+ const std::string& key,
+ const UnwrapOptions& unwrap_options,
+ const UnwrapSecureMessageCallback& callback) override;
+
+ // Sets the next public key to be returned by GenerateKeyPair(). The
+ // corresponding private key will be derived from this public key.
+ void set_next_public_key(const std::string& public_key) {
+ next_public_key_ = public_key;
+ }
+
+ private:
+ std::string next_public_key_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSecureMessageDelegate);
+};
+
+} // namespace proximity_auth
+
+#endif // COMPONENTS_PROXIMITY_AUTH_FAKE_SECURE_MESSAGE_DELEGATE_H
diff --git a/components/proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc b/components/proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc
new file mode 100644
index 0000000..12a02cd
--- /dev/null
+++ b/components/proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc
@@ -0,0 +1,196 @@
+// Copyright 2014 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 "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
+
+#include "base/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace proximity_auth {
+
+namespace {
+
+const char kTestPublicKey[] = "the private key is in another castle";
+const char kPayload[] = "500 tons of uranium";
+const char kSymmetricKey[] = "hunter2";
+const char kPublicMetadata[] = "brought to you by our sponsors";
+const char kAssociatedData[] = "save 20% bytes on your nonce insurance";
+const char kVerificationKeyId[] = "the one with the red stripes";
+const char kDecryptionKeyId[] = "it's in your pocket somewhere";
+
+// Callback for saving the result of GenerateKeys().
+void SaveKeyPair(std::string* private_key_out,
+ std::string* public_key_out,
+ const std::string& private_key,
+ const std::string& public_key) {
+ *private_key_out = private_key;
+ *public_key_out = public_key;
+}
+
+// Callback for saving the result of DeriveKey() and CreateSecureMessage().
+void SaveString(std::string* out, const std::string& value) {
+ *out = value;
+}
+
+// Callback for saving the result of UnwrapSecureMessage().
+void SaveUnwrapResults(std::string* payload_out,
+ securemessage::Header* header_out,
+ bool verified,
+ const std::string& payload,
+ const securemessage::Header& header) {
+ ASSERT_TRUE(verified);
+ *payload_out = payload;
+ *header_out = header;
+}
+
+// Returns the CreateOptions struct to create the test message.
+SecureMessageDelegate::CreateOptions GetCreateOptions(
+ securemessage::EncScheme encryption_scheme,
+ securemessage::SigScheme signature_scheme) {
+ SecureMessageDelegate::CreateOptions create_options;
+ create_options.encryption_scheme = encryption_scheme;
+ create_options.signature_scheme = signature_scheme;
+ create_options.public_metadata = kPublicMetadata;
+ create_options.associated_data = kAssociatedData;
+ create_options.verification_key_id = kVerificationKeyId;
+ create_options.decryption_key_id = kDecryptionKeyId;
+ return create_options;
+}
+
+// Returns the UnwrapOptions struct to unwrap the test message.
+SecureMessageDelegate::UnwrapOptions GetUnwrapOptions(
+ securemessage::EncScheme encryption_scheme,
+ securemessage::SigScheme signature_scheme) {
+ SecureMessageDelegate::UnwrapOptions unwrap_options;
+ unwrap_options.encryption_scheme = encryption_scheme;
+ unwrap_options.signature_scheme = signature_scheme;
+ unwrap_options.associated_data = kAssociatedData;
+ return unwrap_options;
+}
+
+void CheckSerializedSecureMessage(
+ const std::string& serialized_message,
+ const SecureMessageDelegate::CreateOptions& create_options) {
+ securemessage::SecureMessage secure_message;
+ ASSERT_TRUE(secure_message.ParseFromString(serialized_message));
+ securemessage::HeaderAndBody header_and_body;
+ ASSERT_TRUE(
+ header_and_body.ParseFromString(secure_message.header_and_body()));
+
+ const securemessage::Header& header = header_and_body.header();
+ EXPECT_EQ(create_options.signature_scheme, header.signature_scheme());
+ EXPECT_EQ(create_options.encryption_scheme, header.encryption_scheme());
+ EXPECT_EQ(create_options.verification_key_id, header.verification_key_id());
+ EXPECT_EQ(create_options.decryption_key_id, header.decryption_key_id());
+ EXPECT_EQ(create_options.public_metadata, header.public_metadata());
+}
+
+} // namespace
+
+class ProximityAuthFakeSecureMessageDelegateTest : public testing::Test {
+ protected:
+ ProximityAuthFakeSecureMessageDelegateTest() {}
+
+ FakeSecureMessageDelegate delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProximityAuthFakeSecureMessageDelegateTest);
+};
+
+TEST_F(ProximityAuthFakeSecureMessageDelegateTest, GenerateKeyPair) {
+ std::string public_key1, private_key1;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key1, &private_key1));
+ EXPECT_NE(private_key1, public_key1);
+
+ std::string public_key2, private_key2;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key2, &private_key2));
+ EXPECT_NE(private_key2, public_key2);
+
+ EXPECT_NE(public_key1, public_key2);
+ EXPECT_NE(private_key1, private_key2);
+
+ delegate_.set_next_public_key(kTestPublicKey);
+ std::string public_key3, private_key3;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key3, &private_key3));
+ EXPECT_EQ(kTestPublicKey, public_key3);
+ EXPECT_NE(private_key3, public_key3);
+
+ EXPECT_NE(public_key1, public_key3);
+ EXPECT_NE(private_key1, private_key3);
+}
+
+TEST_F(ProximityAuthFakeSecureMessageDelegateTest, DeriveKey) {
+ delegate_.set_next_public_key("key_pair_1");
+ std::string public_key1, private_key1;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key1, &private_key1));
+
+ delegate_.set_next_public_key("key_pair_2");
+ std::string public_key2, private_key2;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key2, &private_key2));
+
+ std::string symmetric_key1, symmetric_key2;
+ delegate_.DeriveKey(private_key1, public_key2,
+ base::Bind(&SaveString, &symmetric_key1));
+ delegate_.DeriveKey(private_key2, public_key1,
+ base::Bind(&SaveString, &symmetric_key2));
+
+ EXPECT_EQ(symmetric_key1, symmetric_key2);
+}
+
+TEST_F(ProximityAuthFakeSecureMessageDelegateTest,
+ CreateAndUnwrapWithSymmetricKey) {
+ // Create SecureMessage using symmetric key.
+ SecureMessageDelegate::CreateOptions create_options =
+ GetCreateOptions(securemessage::AES_256_CBC, securemessage::HMAC_SHA256);
+ std::string serialized_message;
+ delegate_.CreateSecureMessage(kPayload, kSymmetricKey, create_options,
+ base::Bind(&SaveString, &serialized_message));
+
+ CheckSerializedSecureMessage(serialized_message, create_options);
+
+ // Unwrap SecureMessage using symmetric key.
+ SecureMessageDelegate::UnwrapOptions unwrap_options =
+ GetUnwrapOptions(securemessage::AES_256_CBC, securemessage::HMAC_SHA256);
+ std::string payload;
+ securemessage::Header header;
+ delegate_.UnwrapSecureMessage(
+ serialized_message, kSymmetricKey, unwrap_options,
+ base::Bind(&SaveUnwrapResults, &payload, &header));
+
+ EXPECT_EQ(kPayload, payload);
+}
+
+TEST_F(ProximityAuthFakeSecureMessageDelegateTest,
+ CreateAndUnwrapWithAsymmetricKey) {
+ delegate_.set_next_public_key(kTestPublicKey);
+ std::string public_key, private_key;
+ delegate_.GenerateKeyPair(
+ base::Bind(&SaveKeyPair, &public_key, &private_key));
+
+ // Create SecureMessage using asymmetric key.
+ SecureMessageDelegate::CreateOptions create_options =
+ GetCreateOptions(securemessage::NONE, securemessage::ECDSA_P256_SHA256);
+ std::string serialized_message;
+ delegate_.CreateSecureMessage(kPayload, private_key, create_options,
+ base::Bind(&SaveString, &serialized_message));
+
+ CheckSerializedSecureMessage(serialized_message, create_options);
+
+ // Unwrap SecureMessage using symmetric key.
+ SecureMessageDelegate::UnwrapOptions unwrap_options =
+ GetUnwrapOptions(securemessage::NONE, securemessage::ECDSA_P256_SHA256);
+ std::string payload;
+ securemessage::Header header;
+ delegate_.UnwrapSecureMessage(
+ serialized_message, public_key, unwrap_options,
+ base::Bind(&SaveUnwrapResults, &payload, &header));
+
+ EXPECT_EQ(kPayload, payload);
+}
+
+} // proximity_auth
diff --git a/components/proximity_auth/cryptauth/proto/BUILD.gn b/components/proximity_auth/cryptauth/proto/BUILD.gn
index 3d3d3f7..813d594 100644
--- a/components/proximity_auth/cryptauth/proto/BUILD.gn
+++ b/components/proximity_auth/cryptauth/proto/BUILD.gn
@@ -8,5 +8,6 @@ import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
sources = [
"cryptauth_api.proto",
+ "securemessage.proto",
]
}
diff --git a/components/proximity_auth/cryptauth/proto/securemessage.proto b/components/proximity_auth/cryptauth/proto/securemessage.proto
new file mode 100644
index 0000000..9e5d9cb
--- /dev/null
+++ b/components/proximity_auth/cryptauth/proto/securemessage.proto
@@ -0,0 +1,95 @@
+// Copyright 2015 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.
+
+// Definitions related to the SecureMessage format, used by CryptAuth. Do not
+// edit unless transcribing from server definitions.
+syntax = "proto2";
+
+package securemessage;
+
+option optimize_for = LITE_RUNTIME;
+
+message SecureMessage {
+ // Must contain a HeaderAndBody message.
+ required bytes header_and_body = 1;
+ // Signature of header_and_body.
+ required bytes signature = 2;
+}
+
+// Supported "signature" schemes (both symmetric key and public key based).
+enum SigScheme {
+ HMAC_SHA256 = 1;
+ ECDSA_P256_SHA256 = 2;
+ // Not recommended -- use ECDSA_P256_SHA256 instead
+ RSA2048_SHA256 = 3;
+}
+
+// Supported encryption schemes.
+enum EncScheme {
+ // No encryption.
+ NONE = 1;
+ AES_256_CBC = 2;
+}
+
+message Header {
+ required SigScheme signature_scheme = 1;
+ required EncScheme encryption_scheme = 2;
+ // Identifies the verification key.
+ optional bytes verification_key_id = 3;
+ // Identifies the decryption key.
+ optional bytes decryption_key_id = 4;
+ // Encryption may use an IV.
+ optional bytes iv = 5;
+ // Arbitrary per-protocol public data, to be sent with the plain-text header.
+ optional bytes public_metadata = 6;
+ // The length of some associated data that is not sent in this SecureMessage,
+ // but which will be bound to the signature.
+ optional uint32 associated_data_length = 7 [default = 0];
+}
+
+message HeaderAndBody {
+ // Public data about this message (to be bound in the signature).
+ required Header header = 1;
+ // Payload data.
+ required bytes body = 2;
+}
+
+// A list of supported public key types.
+enum PublicKeyType {
+ EC_P256 = 1;
+ RSA2048 = 2;
+ // 2048-bit MODP group 14, from RFC 3526.
+ DH2048_MODP = 3;
+}
+
+// A convenience proto for encoding NIST P-256 elliptic curve public keys.
+message EcP256PublicKey {
+ // x and y are encoded in big-endian two's complement (slightly wasteful)
+ // Client MUST verify (x,y) is a valid point on NIST P256.
+ required bytes x = 1;
+ required bytes y = 2;
+}
+
+// A convenience proto for encoding RSA public keys with small exponents.
+message SimpleRsaPublicKey {
+ // Encoded in big-endian two's complement.
+ required bytes n = 1;
+ optional int32 e = 2 [default = 65537];
+}
+
+// A convenience proto for encoding Diffie-Hellman public keys,
+// for use only when Elliptic Curve based key exchanges are not possible.
+// (Note that the group parameters must be specified separately).
+message DhPublicKey {
+ // Big-endian two's complement encoded group element.
+ required bytes y = 1;
+}
+
+message GenericPublicKey {
+ required PublicKeyType type = 1;
+ optional EcP256PublicKey ec_p256_public_key = 2;
+ optional SimpleRsaPublicKey rsa2048_public_key = 3;
+ // Use only as a last resort.
+ optional DhPublicKey dh2048_public_key = 4;
+}
diff --git a/components/proximity_auth/cryptauth/secure_message_delegate.cc b/components/proximity_auth/cryptauth/secure_message_delegate.cc
new file mode 100644
index 0000000..43f18c0
--- /dev/null
+++ b/components/proximity_auth/cryptauth/secure_message_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright 2015 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 "components/proximity_auth/cryptauth/secure_message_delegate.h"
+
+namespace proximity_auth {
+
+SecureMessageDelegate::SecureMessageDelegate() {
+}
+
+SecureMessageDelegate::~SecureMessageDelegate() {
+}
+
+SecureMessageDelegate::CreateOptions::CreateOptions() {
+}
+
+SecureMessageDelegate::CreateOptions::~CreateOptions() {
+}
+
+SecureMessageDelegate::UnwrapOptions::UnwrapOptions() {
+}
+
+SecureMessageDelegate::UnwrapOptions::~UnwrapOptions() {
+}
+
+} // proximity_auth
diff --git a/components/proximity_auth/cryptauth/secure_message_delegate.h b/components/proximity_auth/cryptauth/secure_message_delegate.h
new file mode 100644
index 0000000..932ebc0a
--- /dev/null
+++ b/components/proximity_auth/cryptauth/secure_message_delegate.h
@@ -0,0 +1,101 @@
+// Copyright 2015 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 COMPONENTS_PROXIMITY_AUTH_SECURE_MESSAGE_DELEGATE_H
+#define COMPONENTS_PROXIMITY_AUTH_SECURE_MESSAGE_DELEGATE_H
+
+#include <string>
+
+#include "base/callback_forward.h"
+#include "components/proximity_auth/cryptauth/proto/securemessage.pb.h"
+
+namespace proximity_auth {
+
+// Interface of delegate responsible for cryptographic operations based on the
+// secure message library. This interface is asynchronous as the current
+// implementation on ChromeOS communicates with a daemon process over IPC.
+class SecureMessageDelegate {
+ public:
+ // Fields specifying how to create a SecureMessage.
+ struct CreateOptions {
+ CreateOptions();
+ ~CreateOptions();
+
+ // The scheme used to encrypt the message.
+ securemessage::EncScheme encryption_scheme;
+ // The scheme used to sign the message.
+ securemessage::SigScheme signature_scheme;
+ // Additional data that is used as part of the signature computation but not
+ // included in the message contents.
+ std::string associated_data;
+ // Plain-text data included in the message header.
+ std::string public_metadata;
+ // Identifies the key to use for verifying the message signature.
+ std::string verification_key_id;
+ // Identifies the key to use for decrypting the message.
+ std::string decryption_key_id;
+ };
+
+ // Fields specifying how to unwrap a SecureMessage.
+ struct UnwrapOptions {
+ UnwrapOptions();
+ ~UnwrapOptions();
+
+ // The scheme used to decrypt the message.
+ securemessage::EncScheme encryption_scheme;
+ // The scheme used to verify the message signature.
+ securemessage::SigScheme signature_scheme;
+ // Additional data that is used as part of the signature computation but not
+ // included in the message contents.
+ std::string associated_data;
+ };
+
+ SecureMessageDelegate();
+ virtual ~SecureMessageDelegate();
+
+ // Generates a new asymmetric key pair.
+ typedef base::Callback<void(const std::string& public_key,
+ const std::string& private_key)>
+ GenerateKeyPairCallback;
+ virtual void GenerateKeyPair(const GenerateKeyPairCallback& callback) = 0;
+
+ // Derives a symmetric key from our private key and the remote device's
+ // public key.
+ typedef base::Callback<void(const std::string& derived_key)>
+ DeriveKeyCallback;
+ virtual void DeriveKey(const std::string& private_key,
+ const std::string& public_key,
+ const DeriveKeyCallback& callback) = 0;
+
+ // Creates a new secure message with a |payload| given the |key| and
+ // |create_options| specifying the cryptographic details.
+ // |callback| will be invoked with the serialized SecureMessage upon success
+ // or the empty string upon failure.
+ typedef base::Callback<void(const std::string& secure_message)>
+ CreateSecureMessageCallback;
+ virtual void CreateSecureMessage(
+ const std::string& payload,
+ const std::string& key,
+ const CreateOptions& create_options,
+ const CreateSecureMessageCallback& callback) = 0;
+
+ // Unwraps |secure_message| given the |key| and |unwrap_options| specifying
+ // the cryptographic details.
+ // |callback| will be invoked with true for the |verified| argument if the
+ // message was verified and decrypted successfully. The |payload| and
+ // |header| fields will be non-empty if the message was verified successfully.
+ typedef base::Callback<void(bool verified,
+ const std::string& payload,
+ const securemessage::Header& header)>
+ UnwrapSecureMessageCallback;
+ virtual void UnwrapSecureMessage(
+ const std::string& serialized_message,
+ const std::string& key,
+ const UnwrapOptions& unwrap_options,
+ const UnwrapSecureMessageCallback& callback) = 0;
+};
+
+} // namespace proximity_auth
+
+#endif // COMPONENTS_PROXIMITY_AUTH_SECURE_MESSAGE_DELEGATE_H