| // 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 <memory> |
| #include <utility> |
| |
| #include "base/json/json_string_value_serializer.h" |
| #include "base/strings/stringprintf.h" |
| |
| namespace { |
| |
| // Keys generated using |GenerateEcP256KeyPair| are in the following format: |
| // "{<key_type>: <key_pair_index>}". |
| // <key_pair_index> is an integer identifying |
| // the key pair. |
| // <key_type> specifies whether the key is public or private. It can have one |
| // of the following valies: |
| const char kEc256PrivateKeyKey[] = "ec_p256_private_key"; |
| const char kEc256PublicKeyKey[] = "ec_p256_public_key"; |
| |
| // Extracts key pair index from a key in format "<key_type>: <key_pair_index>}". |
| int ExtractKeyPairIndexFromKey(const std::string& key, |
| const std::string& key_type) { |
| JSONStringValueDeserializer deserializer(key); |
| std::unique_ptr<base::Value> json_value = |
| deserializer.Deserialize(NULL, NULL); |
| if (!json_value) |
| return -1; |
| |
| base::DictionaryValue* json_dictionary = NULL; |
| if (!json_value->GetAsDictionary(&json_dictionary)) |
| return -1; |
| |
| int key_pair_index = -1; |
| if (!json_dictionary->GetInteger(key_type, &key_pair_index)) |
| return -1; |
| return key_pair_index; |
| } |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| // static |
| bool FakeEasyUnlockClient::IsEcP256KeyPair(const std::string& private_key, |
| const std::string& public_key) { |
| int private_key_index = |
| ExtractKeyPairIndexFromKey(private_key, kEc256PrivateKeyKey); |
| int public_key_index = |
| ExtractKeyPairIndexFromKey(public_key, kEc256PublicKeyKey); |
| |
| return private_key_index > 0 && public_key_index == private_key_index; |
| } |
| |
| FakeEasyUnlockClient::FakeEasyUnlockClient() : generated_keys_count_(0) {} |
| |
| FakeEasyUnlockClient::~FakeEasyUnlockClient() = default; |
| |
| void FakeEasyUnlockClient::Init(dbus::Bus* bus) {} |
| |
| void FakeEasyUnlockClient::GenerateEcP256KeyPair(KeyPairCallback callback) { |
| ++generated_keys_count_; |
| |
| std::move(callback).Run( |
| base::StringPrintf("{\"%s\": %d}", kEc256PrivateKeyKey, |
| generated_keys_count_), |
| base::StringPrintf("{\"%s\": %d}", kEc256PublicKeyKey, |
| generated_keys_count_)); |
| } |
| |
| void FakeEasyUnlockClient::WrapPublicKey(const std::string& key_algorithm, |
| const std::string& public_key, |
| DataCallback callback) { |
| std::move(callback).Run(base::StringPrintf( |
| "{\"wrapped_key\": {\"algorithm\":\"%s\", \"key\":\"%s\"}}", |
| key_algorithm.c_str(), public_key.c_str())); |
| } |
| |
| void FakeEasyUnlockClient::PerformECDHKeyAgreement( |
| const std::string& private_key, |
| const std::string& public_key, |
| DataCallback callback) { |
| int private_key_index = |
| ExtractKeyPairIndexFromKey(private_key, kEc256PrivateKeyKey); |
| int public_key_index = |
| ExtractKeyPairIndexFromKey(public_key, kEc256PublicKeyKey); |
| if (private_key_index < 0 || public_key_index < 0) { |
| std::move(callback).Run(std::string()); |
| return; |
| } |
| |
| // ECDH key agreement should be commutative in respect to key pairs to which |
| // used keys belong, i.e. (key_pair[1].private_key, key_pair[2].public_key) |
| // and (key_pair[2].private_key, key_pair[1].public_key) should produce the |
| // same shared key. To achieve this, identify the created key by sum and |
| // product of the used key pairs. |
| std::move(callback).Run(base::StringPrintf( |
| "{\"secret_key\": [%d, %d]}", private_key_index + public_key_index, |
| private_key_index * public_key_index)); |
| } |
| |
| void FakeEasyUnlockClient::CreateSecureMessage( |
| const std::string& payload, |
| const CreateSecureMessageOptions& options, |
| DataCallback callback) { |
| std::move(callback).Run(base::StringPrintf( |
| "{\"securemessage\": {" |
| "\"payload\": \"%s\"," |
| "\"key\": \"%s\"," |
| "\"associated_data\": \"%s\"," |
| "\"public_metadata\": \"%s\"," |
| "\"verification_key_id\": \"%s\"," |
| "\"decryption_key_id\": \"%s\"," |
| "\"encryption_type\": \"%s\"," |
| "\"signature_type\": \"%s\"" |
| "}}", |
| payload.c_str(), options.key.c_str(), options.associated_data.c_str(), |
| options.public_metadata.c_str(), options.verification_key_id.c_str(), |
| options.decryption_key_id.c_str(), options.encryption_type.c_str(), |
| options.signature_type.c_str())); |
| } |
| |
| void FakeEasyUnlockClient::UnwrapSecureMessage( |
| const std::string& message, |
| const UnwrapSecureMessageOptions& options, |
| DataCallback callback) { |
| // TODO(tbarzic): Verify that |message| is in the format returned by |
| // |CreateSecureMessage| and extract payload, metadata and |
| // verification_key_id from there. |
| std::move(callback).Run(base::StringPrintf( |
| "{\"unwrapped_securemessage\": {" |
| "\"message\": \"%s\"," |
| "\"key\": \"%s\"," |
| "\"associated_data\": \"%s\"," |
| "\"encryption_type\": \"%s\"," |
| "\"signature_type\": \"%s\"" |
| "}}", |
| message.c_str(), options.key.c_str(), options.associated_data.c_str(), |
| options.encryption_type.c_str(), options.signature_type.c_str())); |
| } |
| |
| } // namespace chromeos |