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 "log/log.h"
22 #include "module_file.h"
23 #include "module_utils.h"
24 #include "unique_fd.h"
25
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif
31
32 using namespace OHOS::SysInstaller;
33 using namespace Updater;
34
ParseReadParam(const std::string & path,const int64_t offset,const uint64_t numBytes,off_t & outOffset,size_t & outCount)35 static bool ParseReadParam(const std::string &path, const int64_t offset, const uint64_t numBytes, off_t &outOffset,
36 size_t &outCount)
37 {
38 std::unique_ptr<ModuleFile> file = ModuleFile::Open(path);
39 if (file == nullptr) {
40 LOG(ERROR) << "failed to parse file " << path;
41 return false;
42 }
43 if (!file->GetImageStat().has_value()) {
44 LOG(ERROR) << path << " has no image";
45 return false;
46 }
47 int64_t imageOffset = static_cast<int64_t>(file->GetImageStat().value().imageOffset);
48 int64_t imageSize = static_cast<int64_t>(file->GetImageStat().value().imageSize);
49 outOffset = offset + imageOffset;
50 if (offset < 0) {
51 outOffset += imageSize;
52 }
53 if (outOffset < imageOffset) {
54 LOG(ERROR) << "invalid offset " << offset;
55 return false;
56 }
57 outCount = imageOffset + imageSize - outOffset;
58 if (outCount > numBytes) {
59 outCount = numBytes;
60 }
61 return true;
62 }
63
HvbReadFromPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,void * buf,uint64_t * outNumRead)64 static enum hvb_io_errno HvbReadFromPartition(
65 struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t numBytes, void *buf, uint64_t *outNumRead)
66 {
67 if (partition == nullptr) {
68 LOG(ERROR) << "partition is null";
69 return HVB_IO_ERROR_IO;
70 }
71 if (buf == nullptr) {
72 LOG(ERROR) << "buf is null";
73 return HVB_IO_ERROR_IO;
74 }
75
76 std::string path = std::string(partition);
77 std::string realPath = GetRealPath(path);
78 if (realPath.empty()) {
79 LOG(ERROR) << "invalid path " << path;
80 return HVB_IO_ERROR_IO;
81 }
82 off_t realOffset = 0;
83 size_t count = 0;
84 if (!ParseReadParam(path, offset, numBytes, realOffset, count)) {
85 return HVB_IO_ERROR_IO;
86 }
87
88 OHOS::UniqueFd fd(open(realPath.c_str(), O_RDONLY | O_CLOEXEC));
89 if (fd.Get() == -1) {
90 LOG(ERROR) << "failed to open file " << realPath << " err=" << errno;
91 return HVB_IO_ERROR_IO;
92 }
93 if (!ReadFullyAtOffset(fd.Get(), reinterpret_cast<uint8_t *>(buf), count, realOffset)) {
94 LOG(ERROR) << "failed to read file " << realPath;
95 return HVB_IO_ERROR_IO;
96 }
97 if (outNumRead != nullptr) {
98 *outNumRead = count;
99 }
100
101 return HVB_IO_OK;
102 }
103
HvbWriteToPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,const void * buf)104 static enum hvb_io_errno HvbWriteToPartition(
105 struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t numBytes, const void *buf)
106 {
107 return HVB_IO_OK;
108 }
109
HvbInvalidateKey(struct hvb_ops * ops,const uint8_t * publicKeyData,uint64_t publicKeyLength,const uint8_t * publicKeyMetadata,uint64_t publicKeyMetadataLength,bool * outIsTrusted)110 static enum hvb_io_errno HvbInvalidateKey(struct hvb_ops *ops, const uint8_t *publicKeyData, uint64_t publicKeyLength,
111 const uint8_t *publicKeyMetadata, uint64_t publicKeyMetadataLength, bool *outIsTrusted)
112 {
113 if (outIsTrusted == nullptr) {
114 return HVB_IO_ERROR_IO;
115 }
116
117 *outIsTrusted = true;
118
119 return HVB_IO_OK;
120 }
121
HvbReadRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t * outRollbackIndex)122 static enum hvb_io_errno HvbReadRollbackIdx(
123 struct hvb_ops *ops, uint64_t rollBackIndexLocation, uint64_t *outRollbackIndex)
124 {
125 if (outRollbackIndex == nullptr) {
126 return HVB_IO_ERROR_IO;
127 }
128
129 // return 0 as we only need to set up HVB HASHTREE partition
130 *outRollbackIndex = 0;
131
132 return HVB_IO_OK;
133 }
134
HvbWriteRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t rollbackIndex)135 static enum hvb_io_errno HvbWriteRollbackIdx(
136 struct hvb_ops *ops, uint64_t rollBackIndexLocation, uint64_t rollbackIndex)
137 {
138 return HVB_IO_OK;
139 }
140
HvbReadLockState(struct hvb_ops * ops,bool * lock_state)141 static enum hvb_io_errno HvbReadLockState(struct hvb_ops *ops, bool *lock_state)
142 {
143 return HVB_IO_OK;
144 }
145
HvbGetSizeOfPartition(struct hvb_ops * ops,const char * partition,uint64_t * size)146 static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops *ops, const char *partition, uint64_t *size)
147 {
148 if (size == nullptr) {
149 return HVB_IO_ERROR_IO;
150 }
151
152 // The function is for bootloader to load entire content of HVB HASH
153 // partition. In user-space, return 0 as we only need to set up HVB
154 // HASHTREE partitions.
155 *size = 0;
156 return HVB_IO_OK;
157 }
158
159 static struct hvb_ops g_hvb_ops = {
160 .user_data = &g_hvb_ops,
161 .read_partition = HvbReadFromPartition,
162 .write_partition = HvbWriteToPartition,
163 .valid_rvt_key = HvbInvalidateKey,
164 .read_rollback = HvbReadRollbackIdx,
165 .write_rollback = HvbWriteRollbackIdx,
166 .read_lock_state = HvbReadLockState,
167 .get_partiton_size = HvbGetSizeOfPartition,
168 };
169
ModuleHvbGetOps(void)170 struct hvb_ops *ModuleHvbGetOps(void)
171 {
172 return &g_hvb_ops;
173 }
174
175 #ifdef __cplusplus
176 #if __cplusplus
177 }
178 #endif
179 #endif