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