1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "module_hvb_ops.h"
17 
18 #include <cerrno>
19 #include <fcntl.h>
20 
21 #include "directory_ex.h"
22 #include "log/log.h"
23 #include "module_constants.h"
24 #include "module_file.h"
25 #include "module_utils.h"
26 #include "unique_fd.h"
27 
28 #ifdef __cplusplus
29 #if __cplusplus
30 extern "C" {
31 #endif
32 #endif
33 
34 using namespace OHOS::SysInstaller;
35 using namespace Updater;
36 
ParseReadParam(const std::string & path,const int64_t offset,const uint64_t numBytes,off_t & outOffset,size_t & outCount)37 static bool ParseReadParam(const std::string &path, const int64_t offset, const uint64_t numBytes, off_t &outOffset,
38     size_t &outCount)
39 {
40     std::string modulePath = OHOS::ExtractFilePath(path) + HMP_INFO_NAME;
41     std::unique_ptr<ModuleFile> file = ModuleFile::Open(modulePath);
42     if (file == nullptr) {
43         LOG(ERROR) << "failed to parse file " << modulePath;
44         return false;
45     }
46     if (!file->GetImageStat().has_value()) {
47         LOG(ERROR) << modulePath << " has no image";
48         return false;
49     }
50     int64_t imageOffset = static_cast<int64_t>(file->GetImageStat().value().imageOffset);
51     int64_t imageSize = static_cast<int64_t>(file->GetImageStat().value().imageSize);
52     outOffset = offset + imageOffset;
53     if (offset < 0) {
54         outOffset += imageSize;
55     }
56     if (outOffset < imageOffset) {
57         LOG(ERROR) << "invalid offset " << offset;
58         return false;
59     }
60     outCount = imageOffset + imageSize - outOffset;
61     if (outCount > numBytes) {
62         outCount = numBytes;
63     }
64     return true;
65 }
66 
HvbReadFromPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,void * buf,uint64_t * outNumRead)67 static enum hvb_io_errno HvbReadFromPartition(
68     struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t numBytes, void *buf, uint64_t *outNumRead)
69 {
70     if (partition == nullptr) {
71         LOG(ERROR) << "partition is null";
72         return HVB_IO_ERROR_IO;
73     }
74     if (buf == nullptr) {
75         LOG(ERROR) << "buf is null";
76         return HVB_IO_ERROR_IO;
77     }
78 
79     std::string path = std::string(partition);
80     std::string realPath = GetRealPath(path);
81     if (realPath.empty()) {
82         LOG(ERROR) << "invalid path " << path;
83         return HVB_IO_ERROR_IO;
84     }
85     off_t realOffset = 0;
86     size_t count = 0;
87     if (!ParseReadParam(path, offset, numBytes, realOffset, count)) {
88         return HVB_IO_ERROR_IO;
89     }
90 
91     OHOS::UniqueFd fd(open(realPath.c_str(), O_RDONLY | O_CLOEXEC));
92     if (fd.Get() == -1) {
93         LOG(ERROR) << "failed to open file " << realPath << " err=" << errno;
94         return HVB_IO_ERROR_IO;
95     }
96     if (!ReadFullyAtOffset(fd.Get(), reinterpret_cast<uint8_t *>(buf), count, realOffset)) {
97         LOG(ERROR) << "failed to read file " << realPath;
98         return HVB_IO_ERROR_IO;
99     }
100     if (outNumRead != nullptr) {
101         *outNumRead = count;
102     }
103 
104     return HVB_IO_OK;
105 }
106 
HvbWriteToPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,const void * buf)107 static enum hvb_io_errno HvbWriteToPartition(
108     struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t numBytes, const void *buf)
109 {
110     return HVB_IO_OK;
111 }
112 
HvbInvalidateKey(struct hvb_ops * ops,const uint8_t * publicKeyData,uint64_t publicKeyLength,const uint8_t * publicKeyMetadata,uint64_t publicKeyMetadataLength,bool * outIsTrusted)113 static enum hvb_io_errno HvbInvalidateKey(struct hvb_ops *ops, const uint8_t *publicKeyData, uint64_t publicKeyLength,
114     const uint8_t *publicKeyMetadata, uint64_t publicKeyMetadataLength, bool *outIsTrusted)
115 {
116     if (outIsTrusted == nullptr) {
117         return HVB_IO_ERROR_IO;
118     }
119 
120     *outIsTrusted = true;
121 
122     return HVB_IO_OK;
123 }
124 
HvbReadRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t * outRollbackIndex)125 static  enum hvb_io_errno HvbReadRollbackIdx(
126     struct hvb_ops *ops, uint64_t rollBackIndexLocation, uint64_t *outRollbackIndex)
127 {
128     if (outRollbackIndex == nullptr) {
129         return HVB_IO_ERROR_IO;
130     }
131 
132     // return 0 as we only need to set up HVB HASHTREE partition
133     *outRollbackIndex = 0;
134 
135     return HVB_IO_OK;
136 }
137 
HvbWriteRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t rollbackIndex)138 static enum hvb_io_errno HvbWriteRollbackIdx(
139     struct hvb_ops *ops, uint64_t rollBackIndexLocation, uint64_t rollbackIndex)
140 {
141     return HVB_IO_OK;
142 }
143 
HvbReadLockState(struct hvb_ops * ops,bool * lock_state)144 static enum hvb_io_errno HvbReadLockState(struct hvb_ops *ops, bool *lock_state)
145 {
146     return HVB_IO_OK;
147 }
148 
HvbGetSizeOfPartition(struct hvb_ops * ops,const char * partition,uint64_t * size)149 static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops *ops, const char *partition, uint64_t *size)
150 {
151     if (size == nullptr) {
152         return HVB_IO_ERROR_IO;
153     }
154 
155     // The function is for bootloader to load entire content of HVB HASH
156     // partition. In user-space, return 0 as we only need to set up HVB
157     // HASHTREE partitions.
158     *size = 0;
159     return HVB_IO_OK;
160 }
161 
162 static struct hvb_ops g_hvb_ops = {
163     .user_data = &g_hvb_ops,
164     .read_partition = HvbReadFromPartition,
165     .write_partition = HvbWriteToPartition,
166     .valid_rvt_key = HvbInvalidateKey,
167     .read_rollback = HvbReadRollbackIdx,
168     .write_rollback = HvbWriteRollbackIdx,
169     .read_lock_state = HvbReadLockState,
170     .get_partiton_size = HvbGetSizeOfPartition,
171 };
172 
ModuleHvbGetOps(void)173 struct hvb_ops *ModuleHvbGetOps(void)
174 {
175     return &g_hvb_ops;
176 }
177 
178 #ifdef __cplusplus
179 #if __cplusplus
180 }
181 #endif
182 #endif