1 // 2 // Copyright (C) 2018 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 17 #ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_VERITY_WRITER_ANDROID_H_ 18 #define UPDATE_ENGINE_PAYLOAD_CONSUMER_VERITY_WRITER_ANDROID_H_ 19 20 #include <memory> 21 #include <string> 22 23 #include <verity/hash_tree_builder.h> 24 #include <base/logging.h> 25 #include <base/posix/eintr_wrapper.h> 26 #include <fec/ecc.h> 27 extern "C" { 28 #include <fec.h> 29 } 30 31 #include "payload_consumer/file_descriptor.h" 32 #include "update_engine/payload_consumer/cached_file_descriptor.h" 33 #include "update_engine/payload_consumer/verity_writer_interface.h" 34 35 namespace chromeos_update_engine { 36 enum class EncodeFECStep { 37 kInitFDStep, 38 kEncodeRoundStep, 39 kWriteStep, 40 kComplete 41 }; 42 class IncrementalEncodeFEC { 43 public: IncrementalEncodeFEC()44 IncrementalEncodeFEC() 45 : rs_char_(nullptr, &free_rs_char), cache_fd_(nullptr, 1 * (1 << 20)) {} 46 // Initialize all member variables needed to performe FEC Computation 47 bool Init(const uint64_t _data_offset, 48 const uint64_t _data_size, 49 const uint64_t _fec_offset, 50 const uint64_t _fec_size, 51 const uint64_t _fec_roots, 52 const uint64_t _block_size, 53 const bool _verify_mode); 54 bool Compute(FileDescriptor* _read_fd, FileDescriptor* _write_fd); 55 void UpdateState(); 56 bool Finished() const; 57 void Reset(); 58 double ReportProgress() const; 59 60 private: 61 brillo::Blob rs_blocks_; 62 brillo::Blob buffer_; 63 brillo::Blob fec_; 64 brillo::Blob fec_read_; 65 EncodeFECStep current_step_; 66 size_t current_round_; 67 size_t num_rounds_; 68 FileDescriptor* read_fd_; 69 FileDescriptor* write_fd_; 70 uint64_t data_offset_; 71 uint64_t data_size_; 72 uint64_t fec_offset_; 73 uint64_t fec_size_; 74 uint64_t fec_roots_; 75 uint64_t block_size_; 76 size_t rs_n_; 77 bool verify_mode_; 78 std::unique_ptr<void, decltype(&free_rs_char)> rs_char_; 79 UnownedCachedFileDescriptor cache_fd_; 80 }; 81 82 class VerityWriterAndroid : public VerityWriterInterface { 83 public: 84 VerityWriterAndroid() = default; 85 ~VerityWriterAndroid() override = default; 86 87 bool Init(const InstallPlan::Partition& partition); 88 bool Update(uint64_t offset, const uint8_t* buffer, size_t size) override; 89 bool Finalize(FileDescriptor* read_fd, FileDescriptor* write_fd) override; 90 bool IncrementalFinalize(FileDescriptor* read_fd, 91 FileDescriptor* write_fd) override; 92 double GetProgress() override; 93 bool FECFinished() const override; 94 // Read [data_offset : data_offset + data_size) from |path| and encode FEC 95 // data, if |verify_mode|, then compare the encoded FEC with the one in 96 // |path|, otherwise write the encoded FEC to |path|. We can't encode as we go 97 // in each Update() like hash tree, because for every rs block, its data are 98 // spreaded across entire |data_size|, unless we can cache all data in 99 // memory, we have to re-read them from disk. 100 static bool EncodeFEC(FileDescriptor* read_fd, 101 FileDescriptor* write_fd, 102 uint64_t data_offset, 103 uint64_t data_size, 104 uint64_t fec_offset, 105 uint64_t fec_size, 106 uint32_t fec_roots, 107 uint32_t block_size, 108 bool verify_mode); 109 static bool EncodeFEC(const std::string& path, 110 uint64_t data_offset, 111 uint64_t data_size, 112 uint64_t fec_offset, 113 uint64_t fec_size, 114 uint32_t fec_roots, 115 uint32_t block_size, 116 bool verify_mode); 117 118 private: 119 // stores the state of EncodeFEC 120 IncrementalEncodeFEC encodeFEC_; 121 bool hash_tree_written_ = false; 122 const InstallPlan::Partition* partition_ = nullptr; 123 124 std::unique_ptr<HashTreeBuilder> hash_tree_builder_; 125 uint64_t total_offset_ = 0; 126 DISALLOW_COPY_AND_ASSIGN(VerityWriterAndroid); 127 }; 128 129 } // namespace chromeos_update_engine 130 131 #endif // UPDATE_ENGINE_PAYLOAD_CONSUMER_VERITY_WRITER_ANDROID_H_ 132