• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <hvb_cmdline.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "beget_ext.h"
23 #include "fs_dm.h"
24 #include "fs_hvb.h"
25 #include "securec.h"
26 
27 #ifdef __cplusplus
28 #if __cplusplus
29 extern "C" {
30 #endif
31 #endif
32 
33 #define PARTITION_PATH_PREFIX "/dev/block/by-name/"
34 #define MAX_EXT_HVB_PARTITION_NUM 1
35 #define FS_HVB_LOCK_STATE_STR_MAX 32
36 
37 static const ExtHvbVerifiedDev g_extVerifiedDev[] = {
38     {
39         .partitionName = "module_update",
40         .pathName = "/data/module_update/active/ModuleTrain/module.img"
41     },
42 };
43 
GetImageSizeForHVB(const int fd,const char * image)44 static int64_t GetImageSizeForHVB(const int fd, const char* image)
45 {
46     char headerBuf[SZ_2KB] = {0};
47     ssize_t nbytes;
48     uint64_t fileSysSize;
49     uint64_t realFileSize;
50 
51     if (fd < 0) {
52         BEGET_LOGE("param is error");
53         return -1;
54     }
55 
56     lseek64(fd, 0, SEEK_SET);
57     nbytes = read(fd, &headerBuf, sizeof(headerBuf));
58     if (nbytes != sizeof(headerBuf)) {
59         BEGET_LOGE("read file system header fail");
60         return -1;
61     }
62 
63     if (CheckAndGetErofsSize(&headerBuf[SZ_1KB], &fileSysSize, image) &&
64         CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
65         BEGET_LOGI("get %s size from erofs and extheader, size=0x%lx", image, realFileSize);
66         return realFileSize;
67     } else if (CheckAndGetExt4Size(&headerBuf[SZ_1KB], &fileSysSize, image) &&
68         CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) {
69         BEGET_LOGI("get %s size from ext4 and extheader, size=0x%lx", image, realFileSize);
70         return realFileSize;
71     } else {
72         BEGET_LOGI("read %s file extheader fail, use the actual img size", image);
73     }
74 
75     return lseek64(fd, 0, SEEK_END);
76 }
77 
IsExtHvbVerifiedPtn(const char * ptn,size_t ptnLen,size_t * outIndex)78 static bool IsExtHvbVerifiedPtn(const char *ptn, size_t ptnLen, size_t *outIndex)
79 {
80     int index;
81     if (ptn == NULL || outIndex == NULL) {
82         BEGET_LOGE("error, invalid ptn");
83         return false;
84     }
85 
86     for (index = 0; index < MAX_EXT_HVB_PARTITION_NUM; index++) {
87         if (strncmp(g_extVerifiedDev[index].partitionName, ptn, ptnLen) == 0) {
88             *outIndex = index;
89             return true;
90         }
91     }
92 
93     return false;
94 }
95 
GetExtHvbVerifiedPath(size_t index)96 static char *GetExtHvbVerifiedPath(size_t index)
97 {
98     char *tmpPath = NULL;
99 
100     if (index >= MAX_EXT_HVB_PARTITION_NUM) {
101         BEGET_LOGE("error, invalid index");
102         return NULL;
103     }
104 
105     size_t pathLen = strnlen(g_extVerifiedDev[index].pathName, FS_HVB_MAX_PATH_LEN);
106     if (pathLen >= FS_HVB_MAX_PATH_LEN) {
107         BEGET_LOGE("error, invalid path");
108         return tmpPath;
109     }
110     tmpPath = malloc(pathLen + 1);
111     if (tmpPath == NULL) {
112         BEGET_LOGE("error, fail to malloc");
113         return NULL;
114     }
115 
116     (void)memset_s(tmpPath, pathLen + 1, 0, pathLen + 1);
117     if (memcpy_s(tmpPath, pathLen + 1, g_extVerifiedDev[index].pathName, pathLen) != 0) {
118         free(tmpPath);
119         BEGET_LOGE("error, fail to copy");
120         return NULL;
121     }
122     return tmpPath;
123 }
124 
HvbGetPartitionPath(const char * partition)125 static char *HvbGetPartitionPath(const char *partition)
126 {
127     int rc;
128     size_t pathLen;
129     char *path = NULL;
130     size_t index;
131     size_t ptnLen = strnlen(partition, HVB_MAX_PARTITION_NAME_LEN);
132     if (ptnLen >= HVB_MAX_PARTITION_NAME_LEN) {
133         BEGET_LOGE("error, invalid ptn name");
134         return NULL;
135     }
136     if (IsExtHvbVerifiedPtn(partition, ptnLen, &index)) {
137         return GetExtHvbVerifiedPath(index);
138     }
139 
140     pathLen = strlen(PARTITION_PATH_PREFIX) + ptnLen;
141     path = calloc(1, pathLen + 1);
142     if (path == NULL) {
143         BEGET_LOGE("error, calloc fail");
144         return NULL;
145     }
146     rc = snprintf_s(path, pathLen + 1, pathLen, "%s%s", PARTITION_PATH_PREFIX,
147                     partition);
148     if (rc < 0) {
149         BEGET_LOGE("error, snprintf_s fail, ret = %d", rc);
150         free(path);
151         return NULL;
152     }
153     return path;
154 }
155 
HvbReadFromPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,void * buf,uint64_t * outNumRead)156 static enum hvb_io_errno HvbReadFromPartition(struct hvb_ops* ops,
157                                               const char* partition,
158                                               int64_t offset, uint64_t numBytes,
159                                               void* buf, uint64_t* outNumRead)
160 {
161     int fd = -1;
162     char *path = NULL;
163     enum hvb_io_errno ret = HVB_IO_ERROR_IO;
164 
165     if (ops == NULL || partition == NULL ||
166         buf == NULL || outNumRead == NULL) {
167         BEGET_LOGE("error, invalid parameter");
168         return HVB_IO_ERROR_IO;
169     }
170 
171     /* get and malloc img path */
172     path = HvbGetPartitionPath(partition);
173     if (path == NULL) {
174         BEGET_LOGE("error, get partition path");
175         ret = HVB_IO_ERROR_OOM;
176         goto exit;
177     }
178 
179     fd = open(path, O_RDONLY | O_CLOEXEC);
180     if (fd < 0) {
181         BEGET_LOGE("error, Failed to open %s, errno = %d", path, errno);
182         ret = HVB_IO_ERROR_IO;
183         goto exit;
184     }
185 
186     if (offset < 0) {
187         int64_t total_size = GetImageSizeForHVB(fd, partition);
188         if (total_size == -1) {
189             BEGET_LOGE("Failed to get the size of the partition %s", partition);
190             ret = HVB_IO_ERROR_IO;
191             goto exit;
192         }
193         offset = total_size + offset;
194     }
195 
196     lseek64(fd, offset, SEEK_SET);
197 
198     ssize_t numRead = read(fd, buf, numBytes);
199     if (numRead < 0 || (size_t)numRead != numBytes) {
200         BEGET_LOGE("Failed to read %lld bytes from %s offset %lld", numBytes,
201                    path, offset);
202         ret = HVB_IO_ERROR_IO;
203         goto exit;
204     }
205 
206     *outNumRead = numRead;
207 
208     ret = HVB_IO_OK;
209 
210 exit:
211 
212     if (path != NULL) {
213         free(path);
214     }
215 
216     if (fd >= 0) {
217         close(fd);
218     }
219     return ret;
220 }
221 
HvbWriteToPartition(struct hvb_ops * ops,const char * partition,int64_t offset,uint64_t numBytes,const void * buf)222 static enum hvb_io_errno HvbWriteToPartition(struct hvb_ops* ops,
223                                              const char* partition,
224                                              int64_t offset, uint64_t numBytes,
225                                              const void* buf)
226 {
227     return HVB_IO_OK;
228 }
229 
HvbInvaldateKey(struct hvb_ops * ops,const uint8_t * publicKeyData,uint64_t publicKeyLength,const uint8_t * publicKeyMetadata,uint64_t publicKeyMetadataLength,bool * outIsTrusted)230 static enum hvb_io_errno HvbInvaldateKey(struct hvb_ops* ops,
231                                          const uint8_t* publicKeyData,
232                                          uint64_t publicKeyLength,
233                                          const uint8_t* publicKeyMetadata,
234                                          uint64_t publicKeyMetadataLength,
235                                          bool* outIsTrusted)
236 {
237     if (outIsTrusted == NULL) {
238         return HVB_IO_ERROR_IO;
239     }
240 
241     *outIsTrusted = true;
242 
243     return HVB_IO_OK;
244 }
245 
HvbReadRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t * outRollbackIndex)246 static enum hvb_io_errno HvbReadRollbackIdx(struct hvb_ops* ops,
247                                             uint64_t rollBackIndexLocation,
248                                             uint64_t* outRollbackIndex)
249 {
250     if (outRollbackIndex == NULL) {
251         return HVB_IO_ERROR_IO;
252     }
253 
254     // return 0 as we only need to set up HVB HASHTREE partitions
255     *outRollbackIndex = 0;
256 
257     return HVB_IO_OK;
258 }
259 
HvbWriteRollbackIdx(struct hvb_ops * ops,uint64_t rollBackIndexLocation,uint64_t rollbackIndex)260 static enum hvb_io_errno HvbWriteRollbackIdx(struct hvb_ops* ops,
261                                              uint64_t rollBackIndexLocation,
262                                              uint64_t rollbackIndex)
263 {
264     return HVB_IO_OK;
265 }
266 
FsHvbGetLockStateStr(char * str,size_t size)267 static int FsHvbGetLockStateStr(char *str, size_t size)
268 {
269     return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_DEV_STATE);
270 }
271 
HvbReadLockState(struct hvb_ops * ops,bool * locked)272 static enum hvb_io_errno HvbReadLockState(struct hvb_ops *ops,
273                                           bool *locked)
274 {
275     char lockState[FS_HVB_LOCK_STATE_STR_MAX] = {0};
276     if (ops == NULL || locked == NULL) {
277         BEGET_LOGE("Invalid lock state parameter");
278         return HVB_IO_ERROR_IO;
279     }
280 
281     int ret = FsHvbGetLockStateStr(&lockState[0], sizeof(lockState));
282     if (ret != 0) {
283         BEGET_LOGE("error 0x%x, get lock state from cmdline", ret);
284         return HVB_IO_ERROR_NO_SUCH_VALUE;
285     }
286 
287     if (strncmp(&lockState[0], "locked", FS_HVB_LOCK_STATE_STR_MAX) == 0) {
288         *locked = true;
289     } else if (strncmp(&lockState[0], "unlocked", FS_HVB_LOCK_STATE_STR_MAX) == 0) {
290         *locked = false;
291     } else {
292         BEGET_LOGE("Invalid lock state");
293         return HVB_IO_ERROR_NO_SUCH_VALUE;
294     }
295 
296     return HVB_IO_OK;
297 }
298 
HvbGetSizeOfPartition(struct hvb_ops * ops,const char * partition,uint64_t * size)299 static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops* ops,
300                                                const char* partition,
301                                                uint64_t* size)
302 {
303     if (size == NULL) {
304         return HVB_IO_ERROR_IO;
305     }
306 
307     // The function is for bootloader to load entire content of HVB HASH
308     // partitions. In user-space, return 0 as we only need to set up HVB
309     // HASHTREE partitions.
310     *size = 0;
311     return HVB_IO_OK;
312 }
313 
314 static struct hvb_ops g_hvb_ops = {
315     .user_data = &g_hvb_ops,
316     .read_partition = HvbReadFromPartition,
317     .write_partition = HvbWriteToPartition,
318     .valid_rvt_key = HvbInvaldateKey,
319     .read_rollback = HvbReadRollbackIdx,
320     .write_rollback = HvbWriteRollbackIdx,
321     .read_lock_state = HvbReadLockState,
322     .get_partiton_size = HvbGetSizeOfPartition,
323 };
324 
FsHvbGetOps(void)325 struct hvb_ops* FsHvbGetOps(void)
326 {
327     return &g_hvb_ops;
328 }
329 
330 #ifdef __cplusplus
331 #if __cplusplus
332 }
333 #endif
334 #endif
335