• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //
2  // Copyright (C) 2020 The Android Open Source Project
3  //
4  // Licensed under the Apache License, Version 2.0 (the "License");
5  // you may not use this file except in compliance with the License.
6  // You may obtain a copy of the License at
7  //
8  //      http://www.apache.org/licenses/LICENSE-2.0
9  //
10  // Unless required by applicable law or agreed to in writing, software
11  // distributed under the License is distributed on an "AS IS" BASIS,
12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  // See the License for the specific language governing permissions and
14  // limitations under the License.
15  
16  #include "host/commands/secure_env/json_serializable.h"
17  
18  #include <fstream>
19  
20  #include <android-base/logging.h>
21  #include <keymaster/serializable.h>
22  
23  #include "host/commands/secure_env/encrypted_serializable.h"
24  #include "host/commands/secure_env/hmac_serializable.h"
25  #include "host/commands/secure_env/primary_key_builder.h"
26  
27  namespace cuttlefish {
28  
29  static constexpr char kUniqueKey[] = "JsonSerializable";
30  
31  class JsonSerializable : public keymaster::Serializable {
32  public:
33    JsonSerializable(Json::Value& json);
34  
35    size_t SerializedSize() const override;
36  
37    uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
38  
39    bool Deserialize(const uint8_t** buf_ptr, const uint8_t* buf_end) override;
40  private:
41    Json::Value& json_;
42  };
43  
JsonSerializable(Json::Value & json)44  JsonSerializable::JsonSerializable(Json::Value& json) : json_(json) {}
45  
SerializedSize() const46  size_t JsonSerializable::SerializedSize() const {
47    Json::StreamWriterBuilder factory;
48    auto serialized = Json::writeString(factory, json_);
49    return serialized.size() + sizeof(uint32_t);
50  }
51  
Serialize(uint8_t * buf,const uint8_t * end) const52  uint8_t* JsonSerializable::Serialize(uint8_t* buf, const uint8_t* end) const {
53    Json::StreamWriterBuilder factory;
54    auto serialized = Json::writeString(factory, json_);
55    if (end - buf < serialized.size() + sizeof(uint32_t)) {
56      LOG(ERROR) << "Not enough space to serialize json";
57      return buf;
58    }
59    return keymaster::append_size_and_data_to_buf(
60        buf, end, serialized.data(), serialized.size());
61  }
62  
Deserialize(const uint8_t ** buf_ptr,const uint8_t * buf_end)63  bool JsonSerializable::Deserialize(
64      const uint8_t** buf_ptr, const uint8_t* buf_end) {
65    size_t size;
66    keymaster::UniquePtr<uint8_t[]> json_bytes;
67    bool success = keymaster::copy_size_and_data_from_buf(
68        buf_ptr, buf_end, &size, &json_bytes);
69    if (!success) {
70      LOG(ERROR) << "Failed to deserialize json bytes";
71      return false;
72    }
73    auto doc_begin = reinterpret_cast<const char*>(json_bytes.get());
74    auto doc_end = doc_begin + size;
75    Json::CharReaderBuilder builder;
76    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
77    std::string errorMessage;
78    if (!reader->parse(doc_begin, doc_end, &json_, &errorMessage)) {
79      LOG(ERROR) << "Failed to parse json: " << errorMessage;
80      return false;
81    }
82    return true;
83  }
84  
WriteProtectedJsonToFile(TpmResourceManager & resource_manager,const std::string & filename,Json::Value json)85  bool WriteProtectedJsonToFile(
86      TpmResourceManager& resource_manager,
87      const std::string& filename,
88      Json::Value json) {
89    JsonSerializable sensitive_material(json);
90    auto parent_key_fn = ParentKeyCreator(kUniqueKey);
91    EncryptedSerializable encryption(
92        resource_manager, parent_key_fn, sensitive_material);
93    auto signing_key_fn = SigningKeyCreator(kUniqueKey);
94    HmacSerializable sign_check(resource_manager, signing_key_fn,
95                                TPM2_SHA256_DIGEST_SIZE, &encryption,
96                                /*aad=*/nullptr);
97  
98    auto size = sign_check.SerializedSize();
99    LOG(INFO) << "size : " << size;
100    std::vector<uint8_t> data(size + 1);
101    uint8_t* buf = data.data();
102    uint8_t* buf_end = buf + data.size();
103    buf = sign_check.Serialize(buf, buf_end);
104    if (buf != (buf_end - 1)) {
105      LOG(ERROR) << "Serialized size did not match up with actual usage.";
106      return false;
107    }
108  
109    std::ofstream file_stream(filename, std::ios::trunc | std::ios::binary);
110    file_stream.write(reinterpret_cast<char*>(data.data()), data.size() - 1);
111    if (!file_stream) {
112      LOG(ERROR) << "Failed to save data to " << filename;
113      return false;
114    }
115    return true;
116  }
117  
ReadProtectedJsonFromFile(TpmResourceManager & resource_manager,const std::string & filename)118  Json::Value ReadProtectedJsonFromFile(
119      TpmResourceManager& resource_manager, const std::string& filename) {
120    std::ifstream file_stream(filename, std::ios::binary | std::ios::ate);
121    std::streamsize size = file_stream.tellg();
122    file_stream.seekg(0, std::ios::beg);
123  
124    if (size <= 0) {
125      LOG(VERBOSE) << "File " << filename << " was empty.";
126      return {};
127    }
128  
129    std::vector<char> buffer(size);
130    if (!file_stream.read(buffer.data(), size)) {
131      LOG(ERROR) << "Unable to read from " << filename;
132      return {};
133    }
134    if (!file_stream) {
135      LOG(ERROR) << "Unable to read from " << filename;
136      return {};
137    }
138  
139    Json::Value json;
140    JsonSerializable sensitive_material(json);
141    auto parent_key_fn = ParentKeyCreator(kUniqueKey);
142    EncryptedSerializable encryption(
143        resource_manager, parent_key_fn, sensitive_material);
144    auto signing_key_fn = SigningKeyCreator(kUniqueKey);
145    HmacSerializable sign_check(resource_manager, signing_key_fn,
146                                TPM2_SHA256_DIGEST_SIZE, &encryption,
147                                /*aad=*/nullptr);
148  
149    auto buf = reinterpret_cast<const uint8_t*>(buffer.data());
150    auto buf_end = buf + buffer.size();
151    if (!sign_check.Deserialize(&buf, buf_end)) {
152      LOG(ERROR) << "Failed to deserialize json data from " << filename;
153      return {};
154    }
155  
156    return json;
157  }
158  
159  }  // namespace cuttlefish
160