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