diff options
author | tengs <tengs@chromium.org> | 2015-04-06 19:53:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-07 02:54:12 +0000 |
commit | bbb566c2518db4a962f5ca529bb8204ec53f94c1 (patch) | |
tree | 95661345e7d39a3e28cbc050666a477e61fbd21f | |
parent | 69fc8e7fe0f3025afb513fce0f5eed95d40778fb (diff) | |
download | chromium_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}
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 |