1 /*
2 * Copyright (c) 2022-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 <errno.h>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20
21 #include "beget_ext.h"
22 #include "fs_dm.h"
23 #include "fs_hvb.h"
24 #include "securec.h"
25
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif
31
32 #define PARTITION_PATH_PREFIX "/dev/block/by-name/"
33
GetImageSizeForHVB(const int fd,const char * image)34 static int64_t GetImageSizeForHVB(const int fd, const char* image)
35 {
36 char headerBuf[SZ_2KB] = {0};
37 ssize_t nbytes;
38 uint64_t fileSysSize;
39 uint64_t realFileSize;
40
41 if (fd < 0) {
42 BEGET_LOGE("param is error");
43 return -1;
44 }
45
46 lseek64(fd, 0, SEEK_SET);
47 nbytes = read(fd, &headerBuf, sizeof(headerBuf));
48 if (nbytes != sizeof(headerBuf)) {
49 BEGET_LOGE("read file system header fail");
50 return -1;
51 }
52
53 if (CheckAndGetErofsSize(&headerBuf[SZ_1KB], &fileSysSize, image) &&
54 CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
55 BEGET_LOGI("get %s size from erofs and extheader, size=0x%lx", image, realFileSize);
56 return realFileSize;
57 } else if (CheckAndGetExt4Size(&headerBuf[SZ_1KB], &fileSysSize, image) &&
58 CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
59 BEGET_LOGI("get %s size from ext4 and extheader, size=0x%lx", image, realFileSize);
60 return realFileSize;
61 } else {
62 BEGET_LOGI("read %s file extheader fail, use the actual img size", image);
63 }
64
65 return lseek64(fd, 0, SEEK_END);
66 }
67
HvbReadFromPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,void * buf,uint64_t * outNumRead)68 static enum hvb_io_errno HvbReadFromPartition(struct hvb_ops* ops,
69 const char* partition,
70 int64_t offset, uint64_t numBytes,
71 void* buf, uint64_t* outNumRead)
72 {
73 int rc;
74 int fd = -1;
75 char* path = NULL;
76 size_t pathLen = 0;
77 enum hvb_io_errno ret = HVB_IO_ERROR_IO;
78
79 if (ops == NULL || partition == NULL ||
80 buf == NULL || outNumRead == NULL) {
81 BEGET_LOGE("error, invalid parameter");
82 return HVB_IO_ERROR_IO;
83 }
84
85 pathLen = strlen(PARTITION_PATH_PREFIX) + strlen(partition);
86 path = calloc(1, pathLen + 1);
87 if (path == NULL) {
88 BEGET_LOGE("error, calloc fail");
89 return HVB_IO_ERROR_OOM;
90 }
91
92 rc = snprintf_s(path, pathLen + 1, pathLen, "%s%s", PARTITION_PATH_PREFIX,
93 partition);
94 if (rc < 0) {
95 BEGET_LOGE("error, snprintf_s fail, ret = %d", rc);
96 ret = HVB_IO_ERROR_IO;
97 goto exit;
98 }
99
100 fd = open(path, O_RDONLY | O_CLOEXEC);
101 if (fd < 0) {
102 BEGET_LOGE("error, Failed to open %s, errno = %d", path, errno);
103 ret = HVB_IO_ERROR_IO;
104 goto exit;
105 }
106
107 if (offset < 0) {
108 int64_t total_size = GetImageSizeForHVB(fd, partition);
109 if (total_size == -1) {
110 BEGET_LOGE("Failed to get the size of the partition %s", partition);
111 ret = HVB_IO_ERROR_IO;
112 goto exit;
113 }
114 offset = total_size + offset;
115 }
116
117 lseek64(fd, offset, SEEK_SET);
118
119 ssize_t numRead = read(fd, buf, numBytes);
120 if (numRead < 0 || (size_t)numRead != numBytes) {
121 BEGET_LOGE("Failed to read %lld bytes from %s offset %lld", numBytes,
122 path, offset);
123 ret = HVB_IO_ERROR_IO;
124 goto exit;
125 }
126
127 *outNumRead = numRead;
128
129 ret = HVB_IO_OK;
130
131 exit:
132
133 if (path != NULL) {
134 free(path);
135 }
136
137 if (fd >= 0) {
138 close(fd);
139 }
140 return ret;
141 }
142
HvbWriteToPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,const void * buf)143 static enum hvb_io_errno HvbWriteToPartition(struct hvb_ops* ops,
144 const char* partition,
145 int64_t offset, uint64_t numBytes,
146 const void* buf)
147 {
148 return HVB_IO_OK;
149 }
150
HvbInvaldateKey(struct hvb_ops * ops,const uint8_t * publicKeyData,uint64_t publicKeyLength,const uint8_t * publicKeyMetadata,uint64_t publicKeyMetadataLength,bool * outIsTrusted)151 static enum hvb_io_errno HvbInvaldateKey(struct hvb_ops* ops,
152 const uint8_t* publicKeyData,
153 uint64_t publicKeyLength,
154 const uint8_t* publicKeyMetadata,
155 uint64_t publicKeyMetadataLength,
156 bool* outIsTrusted)
157 {
158 if (outIsTrusted == NULL) {
159 return HVB_IO_ERROR_IO;
160 }
161
162 *outIsTrusted = true;
163
164 return HVB_IO_OK;
165 }
166
HvbReadRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t * outRollbackIndex)167 static enum hvb_io_errno HvbReadRollbackIdx(struct hvb_ops* ops,
168 uint64_t rollBackIndexLocation,
169 uint64_t* outRollbackIndex)
170 {
171 if (outRollbackIndex == NULL) {
172 return HVB_IO_ERROR_IO;
173 }
174
175 // return 0 as we only need to set up HVB HASHTREE partitions
176 *outRollbackIndex = 0;
177
178 return HVB_IO_OK;
179 }
180
HvbWriteRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t rollbackIndex)181 static enum hvb_io_errno HvbWriteRollbackIdx(struct hvb_ops* ops,
182 uint64_t rollBackIndexLocation,
183 uint64_t rollbackIndex)
184 {
185 return HVB_IO_OK;
186 }
187
HvbReadLockState(struct hvb_ops * ops,bool * lock_state)188 static enum hvb_io_errno HvbReadLockState(struct hvb_ops* ops,
189 bool* lock_state)
190 {
191 return HVB_IO_OK;
192 }
193
HvbGetSizeOfPartition(struct hvb_ops * ops,const char * partition,uint64_t * size)194 static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops* ops,
195 const char* partition,
196 uint64_t* size)
197 {
198 if (size == NULL) {
199 return HVB_IO_ERROR_IO;
200 }
201
202 // The function is for bootloader to load entire content of HVB HASH
203 // partitions. In user-space, return 0 as we only need to set up HVB
204 // HASHTREE partitions.
205 *size = 0;
206 return HVB_IO_OK;
207 }
208
209 static struct hvb_ops g_hvb_ops = {
210 .user_data = &g_hvb_ops,
211 .read_partition = HvbReadFromPartition,
212 .write_partition = HvbWriteToPartition,
213 .valid_rvt_key = HvbInvaldateKey,
214 .read_rollback = HvbReadRollbackIdx,
215 .write_rollback = HvbWriteRollbackIdx,
216 .read_lock_state = HvbReadLockState,
217 .get_partiton_size = HvbGetSizeOfPartition,
218 };
219
FsHvbGetOps(void)220 struct hvb_ops* FsHvbGetOps(void)
221 {
222 return &g_hvb_ops;
223 }
224
225 #ifdef __cplusplus
226 #if __cplusplus
227 }
228 #endif
229 #endif
230