// 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 "chromeos/dbus/fake_easy_unlock_client.h" #include #include "base/bind.h" #include "testing/gtest/include/gtest/gtest.h" namespace { // Callback for |GenerateEcP256KeyPair| method. Saves keys returned by the // method in |private_key_target| and |public_key_target|. void RecordKeyPair(std::string* private_key_target, std::string* public_key_target, const std::string& private_key_source, const std::string& public_key_source) { *private_key_target = private_key_source; *public_key_target = public_key_source; } // Callback for |EasyUnlockClient| methods that return a single piece of data. // It saves the returned data in |data_target|. void RecordData(std::string* data_target, const std::string& data_source) { *data_target = data_source; } TEST(FakeEasyUnlockClientTest, GenerateEcP256KeyPair) { chromeos::FakeEasyUnlockClient client; std::string private_key_1; std::string public_key_1; client.GenerateEcP256KeyPair( base::Bind(&RecordKeyPair, &private_key_1, &public_key_1)); ASSERT_EQ("{\"ec_p256_private_key\": 1}", private_key_1); ASSERT_EQ("{\"ec_p256_public_key\": 1}", public_key_1); std::string private_key_2; std::string public_key_2; client.GenerateEcP256KeyPair( base::Bind(&RecordKeyPair, &private_key_2, &public_key_2)); ASSERT_EQ("{\"ec_p256_private_key\": 2}", private_key_2); ASSERT_EQ("{\"ec_p256_public_key\": 2}", public_key_2); EXPECT_NE(private_key_1, private_key_2); EXPECT_NE(public_key_1, public_key_2); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair) { ASSERT_TRUE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_private_key\": 12}", "{\"ec_p256_public_key\": 12}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_KeysFromDiffrentPairs) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_private_key\": 12}", "{\"ec_p256_public_key\": 34}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_KeyOrderSwitched) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_public_key\": 34}", "{\"ec_p256_private_key\": 34}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PrivateKeyInvalidFormat) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "\"ec_p256_private_key\": 12", "{\"ec_p256_public_key\": 12}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PublicKeyInvalidFormat) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_private_key\": 12}", "\"ec_p256_public_key\": 12")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PrivateKeyInvalidDictKey) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"invalid\": 12}", "{\"ec_p256_public_key\": 12}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_PublicKeyInvalidDictKey) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_private_key\": 12}", "{\"invalid\": 12}")); } TEST(FakeEasyUnlockClientTest, IsEcP256KeyPair_InvalidDictValues) { ASSERT_FALSE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( "{\"ec_p256_private_key\": \"12\"}", "{\"ec_p256_public_key\": \"12\"}")); } // Verifies the fake |PerformECDHKeyAgreement| method is symetric in respect to // key pairs from which private and public key used in the key agreement // originate. TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementSuccess) { chromeos::FakeEasyUnlockClient client; // (Fake) key pairs used in the test to generate fake shared keys. const std::string private_key_1 = "{\"ec_p256_private_key\": 32}"; const std::string public_key_1 = "{\"ec_p256_public_key\": 32}"; const std::string private_key_2 = "{\"ec_p256_private_key\": 352}"; const std::string public_key_2 = "{\"ec_p256_public_key\": 352}"; const std::string private_key_3 = "{\"ec_p256_private_key\": 432}"; const std::string public_key_3 = "{\"ec_p256_public_key\": 432}"; // Generate shared key for key pairs 1 and 2, using private key from the // second key pair and public key from the first key pair. std::string shared_key_1; client.PerformECDHKeyAgreement(private_key_2, public_key_1, base::Bind(&RecordData, &shared_key_1)); EXPECT_FALSE(shared_key_1.empty()); // Generate shared key for key pairs 1 and 2, using private key from the // first key pair and public key from the second key pair. std::string shared_key_2; client.PerformECDHKeyAgreement(private_key_1, public_key_2, base::Bind(&RecordData, &shared_key_2)); EXPECT_FALSE(shared_key_2.empty()); // The generated keys should be equal. They were generated using keys from // the same key pairs, even though key pairs from which private and public key // originate were switched. EXPECT_EQ(shared_key_1, shared_key_2); // Generate a key using key pairs 1 and 3. std::string shared_key_3; client.PerformECDHKeyAgreement(private_key_1, public_key_3, base::Bind(&RecordData, &shared_key_3)); EXPECT_FALSE(shared_key_3.empty()); // The new key should be different from the previously generated ones, since // the used key pairs are different. EXPECT_NE(shared_key_3, shared_key_1); EXPECT_NE(shared_key_3, shared_key_1); } TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyOrderSwitched) { chromeos::FakeEasyUnlockClient client; const std::string private_key = "{\"ec_p256_private_key\": 415}"; const std::string public_key = "{\"ec_p256_public_key\": 345}"; std::string shared_key; client.PerformECDHKeyAgreement(public_key, private_key, base::Bind(&RecordData, &shared_key)); EXPECT_TRUE(shared_key.empty()); } TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyDictKeyInvalid) { chromeos::FakeEasyUnlockClient client; const std::string private_key = "{\"ec_p256_private_key_invalid\": 415}"; const std::string public_key = "{\"ec_p256_public_key_invalid\": 345}"; std::string shared_key; client.PerformECDHKeyAgreement(private_key, public_key, base::Bind(&RecordData, &shared_key)); EXPECT_TRUE(shared_key.empty()); } TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyDictValueInvalid) { chromeos::FakeEasyUnlockClient client; const std::string private_key = "{\"ec_p256_private_key\": 415}"; const std::string public_key = "{\"ec_p256_public_key\": \"345__\"}"; std::string shared_key; client.PerformECDHKeyAgreement(private_key, public_key, base::Bind(&RecordData, &shared_key)); EXPECT_TRUE(shared_key.empty()); } TEST(FakeEasyUnlockClientTest, ECDHKeyAgreementFailsIfKeyFormatInvalid) { chromeos::FakeEasyUnlockClient client; const std::string private_key = "invalid"; const std::string public_key = "{\"ec_p256_public_key\": 345}"; std::string shared_key; client.PerformECDHKeyAgreement(private_key, public_key, base::Bind(&RecordData, &shared_key)); EXPECT_TRUE(shared_key.empty()); } TEST(FakeEasyUnlockClientTest, CreateSecureMessage) { chromeos::FakeEasyUnlockClient client; std::string message; chromeos::EasyUnlockClient::CreateSecureMessageOptions options; options.key = "KEY"; options.associated_data = "ASSOCIATED_DATA"; options.public_metadata = "PUBLIC_METADATA"; options.verification_key_id = "VERIFICATION_KEY_ID"; options.decryption_key_id = "DECRYPTION_KEY_ID"; options.encryption_type = "ENCRYPTION_TYPE"; options.signature_type = "SIGNATURE_TYPE"; client.CreateSecureMessage( "PAYLOAD", options, base::Bind(&RecordData, &message)); const std::string expected_message( "{\"securemessage\": {" "\"payload\": \"PAYLOAD\"," "\"key\": \"KEY\"," "\"associated_data\": \"ASSOCIATED_DATA\"," "\"public_metadata\": \"PUBLIC_METADATA\"," "\"verification_key_id\": \"VERIFICATION_KEY_ID\"," "\"decryption_key_id\": \"DECRYPTION_KEY_ID\"," "\"encryption_type\": \"ENCRYPTION_TYPE\"," "\"signature_type\": \"SIGNATURE_TYPE\"}" "}"); ASSERT_EQ(expected_message, message); } TEST(FakeEasyUnlockClientTest, UnwrapSecureMessage) { chromeos::FakeEasyUnlockClient client; std::string message; chromeos::EasyUnlockClient::UnwrapSecureMessageOptions options; options.key = "KEY"; options.associated_data = "ASSOCIATED_DATA"; options.encryption_type = "ENCRYPTION_TYPE"; options.signature_type = "SIGNATURE_TYPE"; client.UnwrapSecureMessage( "MESSAGE", options, base::Bind(&RecordData, &message)); const std::string expected_message( "{\"unwrapped_securemessage\": {" "\"message\": \"MESSAGE\"," "\"key\": \"KEY\"," "\"associated_data\": \"ASSOCIATED_DATA\"," "\"encryption_type\": \"ENCRYPTION_TYPE\"," "\"signature_type\": \"SIGNATURE_TYPE\"}" "}"); ASSERT_EQ(expected_message, message); } } // namespace