1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/json/json_string_value_serializer.h"
6#include "base/strings/stringprintf.h"
7#include "chromeos/dbus/fake_easy_unlock_client.h"
8
9namespace {
10
11// Keys generated using |GenerateEcP256KeyPair| are in the following format:
12// "{<key_type>: <key_pair_index>}".
13// <key_pair_index> is an integer identifying
14// the key pair.
15// <key_type> specifies whether the key is public or private. It can have one
16// of the following valies:
17const char kEc256PrivateKeyKey[] = "ec_p256_private_key";
18const char kEc256PublicKeyKey[] = "ec_p256_public_key";
19
20// Extracts key pair index from a key in format "<key_type>: <key_pair_index>}".
21int ExtractKeyPairIndexFromKey(const std::string& key,
22                               const std::string& key_type) {
23  JSONStringValueSerializer serializer(key);
24  scoped_ptr<base::Value> json_value(serializer.Deserialize(NULL, NULL));
25  if (!json_value)
26    return -1;
27
28  base::DictionaryValue* json_dictionary = NULL;
29  if (!json_value->GetAsDictionary(&json_dictionary))
30    return -1;
31
32  int key_pair_index = -1;
33  if (!json_dictionary->GetInteger(key_type, &key_pair_index))
34    return -1;
35  return key_pair_index;
36}
37
38}  // namespace
39
40namespace chromeos {
41
42// static
43bool FakeEasyUnlockClient::IsEcP256KeyPair(const std::string& private_key,
44                                           const std::string& public_key) {
45  int private_key_index =
46      ExtractKeyPairIndexFromKey(private_key, kEc256PrivateKeyKey);
47  int public_key_index =
48      ExtractKeyPairIndexFromKey(public_key, kEc256PublicKeyKey);
49
50  return private_key_index > 0  && public_key_index == private_key_index;
51}
52
53FakeEasyUnlockClient::FakeEasyUnlockClient() : generated_keys_count_(0) {}
54
55FakeEasyUnlockClient::~FakeEasyUnlockClient() {}
56
57void FakeEasyUnlockClient::Init(dbus::Bus* bus) {}
58
59void FakeEasyUnlockClient::GenerateEcP256KeyPair(
60    const KeyPairCallback& callback) {
61  ++generated_keys_count_;
62
63  callback.Run(
64      base::StringPrintf("{\"%s\": %d}",
65                         kEc256PrivateKeyKey,
66                         generated_keys_count_),
67      base::StringPrintf("{\"%s\": %d}",
68                         kEc256PublicKeyKey,
69                         generated_keys_count_));
70}
71
72void FakeEasyUnlockClient::PerformECDHKeyAgreement(
73    const std::string& private_key,
74    const std::string& public_key,
75    const DataCallback& callback) {
76  int private_key_index =
77      ExtractKeyPairIndexFromKey(private_key, kEc256PrivateKeyKey);
78  int public_key_index =
79      ExtractKeyPairIndexFromKey(public_key, kEc256PublicKeyKey);
80  if (private_key_index < 0 || public_key_index < 0) {
81    callback.Run("");
82    return;
83  }
84
85  // ECDH key agreement should be commutative in respect to key pairs to which
86  // used keys belong, i.e. (key_pair[1].private_key, key_pair[2].public_key)
87  // and (key_pair[2].private_key, key_pair[1].public_key) should produce the
88  // same shared key. To achieve this, identify the created key by sum and
89  // product of the used key pairs.
90  callback.Run(base::StringPrintf(
91      "{\"secret_key\": [%d, %d]}",
92      private_key_index + public_key_index,
93      private_key_index * public_key_index));
94}
95
96void FakeEasyUnlockClient::CreateSecureMessage(
97    const std::string& payload,
98    const CreateSecureMessageOptions& options,
99    const DataCallback& callback) {
100  callback.Run(base::StringPrintf(
101      "{\"securemessage\": {"
102          "\"payload\": \"%s\","
103          "\"key\": \"%s\","
104          "\"associated_data\": \"%s\","
105          "\"public_metadata\": \"%s\","
106          "\"verification_key_id\": \"%s\","
107          "\"decryption_key_id\": \"%s\","
108          "\"encryption_type\": \"%s\","
109          "\"signature_type\": \"%s\""
110      "}}",
111      payload.c_str(),
112      options.key.c_str(),
113      options.associated_data.c_str(),
114      options.public_metadata.c_str(),
115      options.verification_key_id.c_str(),
116      options.decryption_key_id.c_str(),
117      options.encryption_type.c_str(),
118      options.signature_type.c_str()));
119}
120
121void FakeEasyUnlockClient::UnwrapSecureMessage(
122    const std::string& message,
123    const UnwrapSecureMessageOptions& options,
124    const DataCallback& callback) {
125  // TODO(tbarzic): Verify that |message| is in the format returned by
126  // |CreateSecureMessage| and extract payload, metadata and
127  // verification_key_id from there.
128  callback.Run(base::StringPrintf(
129      "{\"unwrapped_securemessage\": {"
130          "\"message\": \"%s\","
131          "\"key\": \"%s\","
132          "\"associated_data\": \"%s\","
133          "\"encryption_type\": \"%s\","
134          "\"signature_type\": \"%s\""
135      "}}",
136      message.c_str(),
137      options.key.c_str(),
138      options.associated_data.c_str(),
139      options.encryption_type.c_str(),
140      options.signature_type.c_str()));
141}
142
143}  // namespace chromeos
144