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