• 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 "fs_hvb.h"
17 #include "fs_dm.h"
18 #include "securec.h"
19 #include "fs_manager/ext4_super_block.h"
20 #include "fs_manager/erofs_super_block.h"
21 #include <stdint.h>
22 #include "beget_ext.h"
23 #include "init_utils.h"
24 #include <libhvb.h>
25 #include <libgen.h>
26 #include "hvb_sm2.h"
27 #include "hvb_sm3.h"
28 #include "hookmgr.h"
29 #include "bootstage.h"
30 #include "fs_manager.h"
31 #include "list.h"
32 
33 #ifdef __cplusplus
34 #if __cplusplus
35 extern "C" {
36 #endif
37 #endif
38 
39 #define FS_HVB_VERITY_TARGET_MAX 512
40 #define FS_HVB_BLANK_SPACE_ASCII 32
41 #define FS_HVB_SECTOR_BYTES 512
42 #define FS_HVB_UINT64_MAX_LENGTH 64
43 #define FS_HVB_HASH_ALG_STR_MAX 32
44 
45 #define FS_HVB_DIGEST_SHA256_BYTES 32
46 #define FS_HVB_DIGEST_SHA512_BYTES 64
47 #define FS_HVB_DIGEST_SM3_BYTES 32
48 #define FS_HVB_DIGEST_MAX_BYTES FS_HVB_DIGEST_SHA512_BYTES
49 #define FS_HVB_DIGEST_STR_MAX_BYTES 128
50 #define FS_HVB_DEVPATH_MAX_LEN 128
51 #define FS_HVB_RVT_PARTITION_NAME "rvt"
52 #define FS_HVB_EXT_RVT_PARTITION_NAME "ext_rvt"
53 #define FS_HVB_CMDLINE_PATH "/proc/cmdline"
54 #define FS_HVB_PARTITION_PREFIX "/dev/block/by-name/"
55 #define HVB_CMDLINE_EXT_CERT_DIGEST "ohos.boot.hvb.ext_rvt"
56 #define FS_HVB_SNAPSHOT_PREFIX "/dev/block/"
57 
58 #define HASH_ALGO_SHA256 0
59 #define HASH_ALGO_SHA256_STR "sha256"
60 #define HASH_ALGO_SHA512 2
61 #define HASH_ALGO_SHA512_STR "sha512"
62 #define HASH_ALGO_SM3 3
63 #define HASH_ALGO_SM3_STR "sm3"
64 
65 #define FS_HVB_RETURN_ERR_IF_NULL(__ptr)             \
66     do {                                                \
67         if ((__ptr) == NULL) {                          \
68             BEGET_LOGE("error, %s is NULL\n", #__ptr); \
69             return -1;                                  \
70         }                                               \
71     } while (0)
72 
73 static struct hvb_verified_data *g_vd = NULL;
74 static struct hvb_verified_data *g_extVd = NULL;
75 
GetCurrVerifiedData(InitHvbType hvbType,struct hvb_verified_data *** currVd)76 static enum hvb_errno GetCurrVerifiedData(InitHvbType hvbType, struct hvb_verified_data ***currVd)
77 {
78     if (currVd == NULL) {
79         BEGET_LOGE("error, invalid input");
80         return HVB_ERROR_INVALID_ARGUMENT;
81     }
82     if (hvbType == MAIN_HVB) {
83         *currVd = &g_vd;
84     } else if (hvbType == EXT_HVB) {
85         *currVd = &g_extVd;
86     } else {
87         BEGET_LOGE("error, invalid hvb type");
88         return HVB_ERROR_INVALID_ARGUMENT;
89     }
90 
91     return HVB_OK;
92 }
93 
FsHvbBinToHexChar(char octet)94 static char FsHvbBinToHexChar(char octet)
95 {
96     return octet < 10 ? '0' + octet : 'a' + (octet - 10);
97 }
98 
FsHvbHexCharToBin(char hex)99 static char FsHvbHexCharToBin(char hex)
100 {
101     return '0' <= hex && hex <= '9' ? hex - '0' : 10 + (hex - 'a');
102 }
103 
FsHvbGetHashStr(char * str,size_t size,InitHvbType hvbType)104 static int FsHvbGetHashStr(char *str, size_t size, InitHvbType hvbType)
105 {
106     if (hvbType == MAIN_HVB) {
107         return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_HASH_ALG);
108     }
109 
110     if (hvbType == EXT_HVB) {
111         if (memcpy_s(str, size, HASH_ALGO_SHA256_STR, strlen(HASH_ALGO_SHA256_STR)) != 0) {
112             BEGET_LOGE("fail to copy hvb hash str");
113             return -1;
114         }
115         return 0;
116     }
117 
118     BEGET_LOGE("error, invalid hvbType");
119     return -1;
120 }
121 
FsHvbGetCertDigstStr(char * str,size_t size,InitHvbType hvbType)122 static int FsHvbGetCertDigstStr(char *str, size_t size, InitHvbType hvbType)
123 {
124     if (hvbType == MAIN_HVB) {
125         return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_CERT_DIGEST);
126     }
127 
128     if (hvbType == EXT_HVB) {
129         return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_EXT_CERT_DIGEST);
130     }
131 
132     BEGET_LOGE("error, invalid hvbType");
133     return -1;
134 }
135 
FsHvbComputeSha256(char * digest,uint32_t size,struct hvb_cert_data * certs,uint64_t num_certs)136 static int FsHvbComputeSha256(char *digest, uint32_t size, struct hvb_cert_data *certs, uint64_t num_certs)
137 {
138     int ret;
139     uint64_t n;
140     struct hash_ctx_t ctx = {0};
141 
142     if (size < FS_HVB_DIGEST_SHA256_BYTES) {
143         BEGET_LOGE("error, size=%zu", size);
144         return -1;
145     }
146 
147     ret = hash_ctx_init(&ctx, HASH_ALG_SHA256);
148     if (ret != HASH_OK) {
149         BEGET_LOGE("error 0x%x, sha256 init", ret);
150         return -1;
151     }
152 
153     for (n = 0; n < num_certs; n++) {
154         ret = hash_calc_update(&ctx, certs[n].data.addr, certs[n].data.size);
155         if (ret != HASH_OK) {
156             BEGET_LOGE("error 0x%x, sha256 update", ret);
157             return -1;
158         }
159     }
160 
161     ret = hash_calc_do_final(&ctx, NULL, 0, (uint8_t *)digest, size);
162     if (ret != HASH_OK) {
163         BEGET_LOGE("error 0x%x, sha256 final", ret);
164         return -1;
165     }
166 
167     return 0;
168 }
169 
FsHvbComputeSM3Hash(char * digest,uint32_t * size,struct hvb_cert_data * certs,uint64_t num_certs)170 static int FsHvbComputeSM3Hash(char *digest, uint32_t *size, struct hvb_cert_data *certs, uint64_t num_certs)
171 {
172     BEGET_CHECK(digest != NULL && certs != NULL && size != NULL, return -1);
173     int ret;
174     uint64_t n;
175     struct sm3_ctx_t ctx = {0};
176 
177     if (*size < FS_HVB_DIGEST_SM3_BYTES) {
178         BEGET_LOGE("error, size=%zu", *size);
179         return -1;
180     }
181 
182     ret = hvb_sm3_init(&ctx);
183     if (ret != SM3_OK) {
184         BEGET_LOGE("error 0x%x, sm3 init", ret);
185         return -1;
186     }
187 
188     for (n = 0; n < num_certs; n++) {
189         ret = hvb_sm3_update(&ctx, certs[n].data.addr, certs[n].data.size);
190         if (ret != SM3_OK) {
191             BEGET_LOGE("error 0x%x, sm3 update", ret);
192             return -1;
193         }
194     }
195 
196     ret = hvb_sm3_final(&ctx, (uint8_t *)digest, size);
197     if (ret != SM3_OK) {
198         BEGET_LOGE("error 0x%x, sha256 final", ret);
199         return -1;
200     }
201 
202     return 0;
203 }
204 
FsHvbHexStrToBin(char * bin,size_t bin_size,char * str,size_t str_size)205 static int FsHvbHexStrToBin(char *bin, size_t bin_size, char *str, size_t str_size)
206 {
207     size_t i;
208 
209     if ((str_size & 0x1) != 0 || bin_size < (str_size >> 1)) {
210         BEGET_LOGE("error, bin_size %zu str_size %zu", bin_size, str_size);
211         return -1;
212     }
213 
214     for (i = 0; i < (str_size >> 1); i++) {
215         bin[i] = (FsHvbHexCharToBin(str[2 * i]) << 4) | FsHvbHexCharToBin(str[2 * i + 1]);
216     }
217 
218     return 0;
219 }
220 
FsHvbCheckCertChainDigest(struct hvb_cert_data * certs,uint64_t num_certs,InitHvbType hvbType)221 static int FsHvbCheckCertChainDigest(struct hvb_cert_data *certs, uint64_t num_certs, InitHvbType hvbType)
222 {
223     int ret;
224     size_t digest_len = 0;
225     char hashAlg[FS_HVB_HASH_ALG_STR_MAX] = {0};
226     char certDigest[FS_HVB_DIGEST_MAX_BYTES] = {0};
227     char computeDigest[FS_HVB_DIGEST_MAX_BYTES] = {0};
228     char certDigestStr[FS_HVB_DIGEST_STR_MAX_BYTES + 1] = {0};
229     uint32_t computeDigestLen = FS_HVB_DIGEST_MAX_BYTES;
230 
231     ret = FsHvbGetHashStr(&hashAlg[0], sizeof(hashAlg), hvbType);
232     if (ret != 0) {
233         BEGET_LOGE("error 0x%x, get hash val from cmdline", ret);
234         return ret;
235     }
236 
237     ret = FsHvbGetCertDigstStr(&certDigestStr[0], sizeof(certDigestStr), hvbType);
238     if (ret != 0) {
239         BEGET_LOGE("error 0x%x, get digest val from cmdline", ret);
240         return ret;
241     }
242 
243     ret = FsHvbHexStrToBin(&certDigest[0], sizeof(certDigest), &certDigestStr[0], strlen(certDigestStr));
244     if (ret != 0) {
245         return ret;
246     }
247 
248     if (strcmp(&hashAlg[0], "sha256") == 0) {
249         digest_len = FS_HVB_DIGEST_SHA256_BYTES;
250         ret = FsHvbComputeSha256(computeDigest, computeDigestLen, certs, num_certs);
251     } else if (strcmp(&hashAlg[0], "sm3") == 0) {
252         digest_len = FS_HVB_DIGEST_SM3_BYTES;
253         ret = FsHvbComputeSM3Hash(computeDigest, &computeDigestLen, certs, num_certs);
254     } else {
255         BEGET_LOGE("error, not support alg %s", &hashAlg[0]);
256         return -1;
257     }
258 
259     if (ret != 0) {
260         BEGET_LOGE("error 0x%x, compute hash", ret);
261         return -1;
262     }
263 
264     ret = memcmp(&certDigest[0], &computeDigest[0], digest_len);
265     if (ret != 0) {
266         BEGET_LOGE("error, cert digest not match with cmdline");
267         return -1;
268     }
269 
270     return 0;
271 }
272 
FsHvbInit(InitHvbType hvbType)273 int FsHvbInit(InitHvbType hvbType)
274 {
275     enum hvb_errno rc;
276     struct hvb_verified_data **currVd = NULL;
277     char *rootPartitionName = NULL;
278     rc = GetCurrVerifiedData(hvbType, &currVd);
279     if (rc != HVB_OK) {
280         BEGET_LOGE("error 0x%x, GetCurrVerifiedData", rc);
281         return rc;
282     }
283 
284     // return ok if the hvb is already initialized
285     if (*currVd != NULL) {
286         BEGET_LOGI("Hvb has already been inited");
287         return 0;
288     }
289 
290     if (hvbType == MAIN_HVB) {
291         rootPartitionName = FS_HVB_RVT_PARTITION_NAME;
292     } else {
293         rootPartitionName = FS_HVB_EXT_RVT_PARTITION_NAME;
294     }
295 
296     rc = hvb_chain_verify(FsHvbGetOps(), rootPartitionName, NULL, currVd);
297     if (*currVd == NULL) {
298         BEGET_LOGE("error 0x%x, hvb chain verify, vd is NULL", rc);
299         return rc;
300     }
301 
302     if (rc != HVB_OK) {
303         BEGET_LOGE("error 0x%x, hvb chain verify", rc);
304         hvb_chain_verify_data_free(*currVd);
305         *currVd = NULL;
306         return rc;
307     }
308 
309     rc = FsHvbCheckCertChainDigest((*currVd)->certs, (*currVd)->num_loaded_certs, hvbType);
310     if (rc != 0) {
311         BEGET_LOGE("error 0x%x, cert chain hash", rc);
312         hvb_chain_verify_data_free(*currVd);
313         *currVd = NULL;
314         return rc;
315     }
316 
317     BEGET_LOGI("hvb type %d verify succ in init", hvbType);
318 
319     return 0;
320 }
321 
FsHvbFindVabPartition(const char * devName,HvbDeviceParam * devPara)322 static int FsHvbFindVabPartition(const char *devName, HvbDeviceParam *devPara)
323 {
324     int rc;
325     HOOK_EXEC_OPTIONS options;
326     if (devPara == NULL) {
327         BEGET_LOGE("error, get devPara");
328         return -1;
329     }
330     if (memcpy_s(devPara->partName, sizeof(devPara->partName), devName, strlen(devName)) != 0) {
331         BEGET_LOGE("error, fail to copy shapshot name");
332         return -1;
333     }
334     (void)memset_s(devPara->value, sizeof(devPara->value), 0, sizeof(devPara->value));
335     devPara->reverse = 1;
336     devPara->len = (int)sizeof(devPara->value);
337     options.flags = TRAVERSE_STOP_WHEN_ERROR;
338     options.preHook = NULL;
339     options.postHook = NULL;
340 
341     rc = HookMgrExecute(GetBootStageHookMgr(), INIT_VAB_HVBCHECK, (void*)devPara, &options);
342     BEGET_LOGW("try find partition from snapshot path %s, ret = %d", devName, rc);
343     if (rc == 0) {
344         BEGET_LOGW("found partition %s, len=%d", devPara->value, devPara->len);
345     }
346 
347     return rc;
348 }
349 
FsHvbGetCert(struct hvb_cert * cert,const char * devName,struct hvb_verified_data * vd)350 static int FsHvbGetCert(struct hvb_cert *cert, const char *devName, struct hvb_verified_data *vd)
351 {
352     enum hvb_errno hr;
353     size_t devNameLen = strlen(devName);
354     struct hvb_cert_data *p = vd->certs;
355     struct hvb_cert_data *end = p + vd->num_loaded_certs;
356 
357     // for virtual ab boot, find partition name with snapshot name
358     HvbDeviceParam devPara = {};
359     if (FsHvbFindVabPartition(devName, &devPara) == 0) {
360         devName = devPara.value;
361         devNameLen = strlen(devName);
362     }
363 
364     int bootSlots = GetBootSlots();
365     if (bootSlots > 1) {
366         if (devNameLen <= FS_HVB_AB_SUFFIX_LEN) {
367             BEGET_LOGE("error, devname (%s) is invlaid, devnamelen = %u", devName, devNameLen);
368             return -1;
369         }
370         if (memcmp(devName + devNameLen - FS_HVB_AB_SUFFIX_LEN, "_a", FS_HVB_AB_SUFFIX_LEN) == 0 ||
371             memcmp(devName + devNameLen - FS_HVB_AB_SUFFIX_LEN, "_b", FS_HVB_AB_SUFFIX_LEN) == 0) {
372             BEGET_LOGI("remove ab suffix in %s to match in hvb certs", devName);
373             devNameLen -= FS_HVB_AB_SUFFIX_LEN;
374         }
375     }
376 
377     for (; p < end; p++) {
378         if (devNameLen != strlen(p->partition_name)) {
379             continue;
380         }
381 
382         if (memcmp(p->partition_name, devName, devNameLen) == 0) {
383             break;
384         }
385     }
386 
387     if (p == end) {
388         BEGET_LOGE("error, can't found %s partition", devName);
389         return -1;
390     }
391 
392     hr = hvb_cert_parser(cert, &p->data);
393     if (hr != HVB_OK) {
394         BEGET_LOGE("error 0x%x, parser hvb cert", hr);
395         return -1;
396     }
397 
398     return 0;
399 }
400 
FsHvbVerityTargetAppendString(char ** p,char * end,char * str,size_t len)401 static int FsHvbVerityTargetAppendString(char **p, char *end, char *str, size_t len)
402 {
403     errno_t err;
404 
405     // check range for append string
406     if (*p + len >= end || *p + len < *p) {
407         BEGET_LOGE("error, append string overflow");
408         return -1;
409     }
410     // append string
411     err = memcpy_s(*p, end - *p, str, len);
412     if (err != EOK) {
413         BEGET_LOGE("error 0x%x, cp string fail", err);
414         return -1;
415     }
416     *p += len;
417 
418     // check range for append blank space
419     if (*p + 1 >= end || *p + 1 < *p) {
420         BEGET_LOGE("error, append blank space overflow");
421         return -1;
422     }
423     // append blank space
424     **p = FS_HVB_BLANK_SPACE_ASCII;
425     *p += 1;
426 
427     BEGET_LOGI("append string %s", str);
428 
429     return 0;
430 }
431 
FsHvbVerityTargetAppendOctets(char ** p,char * end,char * octs,size_t octs_len)432 static int FsHvbVerityTargetAppendOctets(char **p, char *end, char *octs, size_t octs_len)
433 {
434     size_t i;
435     int rc;
436     char *str = NULL;
437     size_t str_len = octs_len * 2;
438 
439     str = calloc(1, str_len + 1);
440     if (str == NULL) {
441         BEGET_LOGE("error, calloc str fail");
442         return -1;
443     }
444 
445     for (i = 0; i < octs_len; i++) {
446         str[2 * i] = FsHvbBinToHexChar((octs[i] >> 4) & 0xf);
447         str[2 * i + 1] = FsHvbBinToHexChar(octs[i] & 0xf);
448     }
449 
450     rc = FsHvbVerityTargetAppendString(p, end, str, str_len);
451     if (rc != 0) {
452         BEGET_LOGE("error 0x%x, append str fail", rc);
453     }
454     free(str);
455 
456     return rc;
457 }
458 
FsHvbVerityTargetAppendNum(char ** p,char * end,uint64_t num)459 static int FsHvbVerityTargetAppendNum(char **p, char *end, uint64_t num)
460 {
461     int rc;
462     char num_str[FS_HVB_UINT64_MAX_LENGTH] = {0};
463 
464     rc = sprintf_s(&num_str[0], sizeof(num_str), "%llu", num);
465     if (rc < 0) {
466         BEGET_LOGE("error 0x%x, calloc num_str", rc);
467         return rc;
468     }
469 
470     rc = FsHvbVerityTargetAppendString(p, end, num_str, strlen(&num_str[0]));
471     if (rc != 0) {
472         BEGET_LOGE("error 0x%x, append num_str fail", rc);
473     }
474 
475     return rc;
476 }
477 
478 #define RETURN_ERR_IF_APPEND_STRING_ERR(p, end, str, str_len)                     \
479     do {                                                                          \
480         int __ret = FsHvbVerityTargetAppendString(p, end, str, str_len);          \
481         if (__ret != 0)                                                           \
482             return __ret;                                                         \
483     } while (0)
484 
485 #define RETURN_ERR_IF_APPEND_OCTETS_ERR(p, end, octs, octs_len)                    \
486     do {                                                                          \
487         int __ret = FsHvbVerityTargetAppendOctets(p, end, octs, octs_len);          \
488         if (__ret != 0)                                                           \
489             return __ret;                                                         \
490     } while (0)
491 
492 #define RETURN_ERR_IF_APPEND_DIGIT_ERR(p, end, num)                               \
493     do {                                                                          \
494         int __ret = FsHvbVerityTargetAppendNum(p, end, num);                      \
495         if (__ret != 0)                                                           \
496             return __ret;                                                         \
497     } while (0)
498 
FsHvbGetHashAlgStr(unsigned int hash_algo)499 static char *FsHvbGetHashAlgStr(unsigned int hash_algo)
500 {
501     char *alg = NULL;
502 
503     switch (hash_algo) {
504         case HASH_ALGO_SHA256:
505             alg = HASH_ALGO_SHA256_STR;
506             break;
507 
508         case HASH_ALGO_SHA512:
509             alg = HASH_ALGO_SHA512_STR;
510             break;
511 
512         case HASH_ALGO_SM3:
513             alg = HASH_ALGO_SM3_STR;
514             break;
515 
516         default:
517             alg = NULL;
518             break;
519     }
520 
521     return alg;
522 }
523 
524 /*
525  * add optional fec data if supported, format as below;
526  * <use_fec_from_device> <fec_roots><fec_blocks><fec_start>
527  */
FsHvbVerityTargetAddFecArgs(struct hvb_cert * cert,char * devPath,char ** str,char * end)528 static int FsHvbVerityTargetAddFecArgs(struct hvb_cert *cert, char *devPath, char **str, char *end)
529 {
530     FS_HVB_RETURN_ERR_IF_NULL(cert);
531     FS_HVB_RETURN_ERR_IF_NULL(devPath);
532     FS_HVB_RETURN_ERR_IF_NULL(str);
533     FS_HVB_RETURN_ERR_IF_NULL(end);
534 
535     // append <device>
536     RETURN_ERR_IF_APPEND_STRING_ERR(str, end, USE_FEC_FROM_DEVICE, strlen(USE_FEC_FROM_DEVICE));
537     RETURN_ERR_IF_APPEND_STRING_ERR(str, end, &devPath[0], strlen(devPath));
538 
539     // append <fec_roots>
540     RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_ROOTS, strlen(FEC_ROOTS));
541     RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_num_roots);
542 
543     if (cert->data_block_size == 0 || cert->hash_block_size == 0) {
544         BEGET_LOGE("error, block size is zero");
545         return -1;
546     }
547     // append <fec_blocks>
548     RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_BLOCKS, strlen(FEC_BLOCKS));
549     RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->hash_block_size);
550 
551     // append <fec_start>
552     RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_START, strlen(FEC_START));
553     RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->data_block_size);
554 
555     return 0;
556 }
557 
FsHvbGetFsPrefix(const char * devName)558 static const char *FsHvbGetFsPrefix(const char *devName)
559 {
560     HvbDeviceParam devPara = {};
561     if (FsHvbFindVabPartition(devName, &devPara) == 0) {
562         return FS_HVB_SNAPSHOT_PREFIX;
563     }
564     return FS_HVB_PARTITION_PREFIX;
565 }
566 
567 /*
568  * target->paras is verity table target, format as below;
569  * <version> <dev><hash_dev><data_block_size><hash_block_size>
570  * <num_data_blocks><hash_start_block><algorithm><digest><salt>
571  * [<#opt_params><opt_params>]
572  * exp: 1 /dev/sda1 /dev/sda1 4096 4096 262144 262144 sha256 \
573        xxxxx
574        xxxxx
575  */
576 
FsHvbConstructVerityTarget(DmVerityTarget * target,const char * devName,struct hvb_cert * cert)577 int FsHvbConstructVerityTarget(DmVerityTarget *target, const char *devName, struct hvb_cert *cert)
578 {
579     char *p = NULL;
580     char *end = NULL;
581     char *hashALgo = NULL;
582     char devPath[FS_HVB_DEVPATH_MAX_LEN] = {0};
583 
584     FS_HVB_RETURN_ERR_IF_NULL(target);
585     FS_HVB_RETURN_ERR_IF_NULL(devName);
586     FS_HVB_RETURN_ERR_IF_NULL(cert);
587 
588     target->start = 0;
589     target->length = cert->image_len / FS_HVB_SECTOR_BYTES;
590     target->paras = calloc(1, FS_HVB_VERITY_TARGET_MAX); // simple it, just calloc a big mem
591     if (target->paras == NULL) {
592         BEGET_LOGE("error, alloc target paras");
593         return -1;
594     }
595 
596     if (snprintf_s(&devPath[0], sizeof(devPath), sizeof(devPath) - 1, "%s%s",
597         ((strchr(devName, '/') == NULL) ? FsHvbGetFsPrefix(devName) : ""), devName) == -1) {
598         BEGET_LOGE("error, snprintf_s devPath");
599         return -1;
600     }
601 
602     p = target->paras;
603     end = p + FS_HVB_VERITY_TARGET_MAX;
604 
605     // append <version>
606     RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, 1);
607     // append <dev>
608     RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath));
609     // append <hash_dev>
610     RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath));
611 
612     if (cert->data_block_size == 0 || cert->hash_block_size == 0) {
613         BEGET_LOGE("error, block size is zero");
614         return -1;
615     }
616     // append <data_block_size>
617     RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->data_block_size);
618     // append <hash_block_size>
619     RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hash_block_size);
620     // append <num_data_blocks>
621     RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->image_len / cert->data_block_size);
622     // append <hash_start_block>
623     RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hashtree_offset / cert->hash_block_size);
624 
625     // append <algorithm>
626     hashALgo = FsHvbGetHashAlgStr(cert->hash_algo);
627     if (hashALgo == NULL) {
628         BEGET_LOGE("error, hash alg %d is invalid", cert->hash_algo);
629         return -1;
630     }
631     RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, hashALgo, strlen(hashALgo));
632 
633     // append <digest>
634     RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.digest, cert->digest_size);
635 
636     // append <salt>
637     RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.salt, cert->salt_size);
638 
639     if (cert->fec_size > 0) {
640         if (FsHvbVerityTargetAddFecArgs(cert, devPath, &p, end) != 0) {
641             return -1;
642         }
643     }
644 
645     // remove last blank
646     *(p - 1) = '\0';
647 
648     target->paras_len = strlen(target->paras);
649 
650     return 0;
651 }
652 
FsHvbCreateVerityTarget(DmVerityTarget * target,char * devName,struct hvb_verified_data * vd)653 static int FsHvbCreateVerityTarget(DmVerityTarget *target, char *devName, struct hvb_verified_data *vd)
654 {
655     int rc;
656     struct hvb_cert cert = {0};
657 
658     rc = FsHvbGetCert(&cert, devName, vd);
659     if (rc != 0) {
660         return rc;
661     }
662 
663     rc = FsHvbConstructVerityTarget(target, devName, &cert);
664     if (rc != 0) {
665         BEGET_LOGE("error 0x%x, can't construct verity target", rc);
666         return rc;
667     }
668 
669     return rc;
670 }
671 
FsExtHvbCreateVerityTarget(DmVerityTarget * target,const char * devName,const char * partition,struct hvb_verified_data * vd)672 static int FsExtHvbCreateVerityTarget(DmVerityTarget *target, const char *devName,
673                                       const char *partition, struct hvb_verified_data *vd)
674 {
675     int rc;
676     struct hvb_cert cert = {0};
677 
678     rc = FsHvbGetCert(&cert, partition, vd);
679     if (rc != 0) {
680         return rc;
681     }
682 
683     rc = FsHvbConstructVerityTarget(target, devName, &cert);
684     if (rc != 0) {
685         BEGET_LOGE("error 0x%x, can't construct verity target", rc);
686         return rc;
687     }
688 
689     return rc;
690 }
691 
FsHvbDestoryVerityTarget(DmVerityTarget * target)692 void FsHvbDestoryVerityTarget(DmVerityTarget *target)
693 {
694     if (target != NULL && target->paras != NULL) {
695         free(target->paras);
696         target->paras = NULL;
697     }
698 }
699 
FsHvbSetupHashtree(FstabItem * fsItem)700 int FsHvbSetupHashtree(FstabItem *fsItem)
701 {
702     int rc;
703     DmVerityTarget target = {0};
704     char *dmDevPath = NULL;
705     char *devName = NULL;
706 
707     FS_HVB_RETURN_ERR_IF_NULL(fsItem);
708     FS_HVB_RETURN_ERR_IF_NULL(g_vd);
709 
710     // fsItem->deviceName is like /dev/block/platform/xxx/by-name/system
711     // for vab boot, is like /dev/block/dm-1
712     // we just basename system
713     devName = basename(fsItem->deviceName);
714     if (devName == NULL) {
715         BEGET_LOGE("error, get basename");
716         return -1;
717     }
718 
719     rc = FsHvbCreateVerityTarget(&target, devName, g_vd);
720     if (rc != 0) {
721         BEGET_LOGE("error 0x%x, create verity-table", rc);
722         goto exit;
723     }
724 
725     rc = FsDmCreateDevice(&dmDevPath, devName, &target);
726     if (rc != 0) {
727         BEGET_LOGE("error 0x%x, create dm-verity", rc);
728         goto exit;
729     }
730 
731     rc = FsDmInitDmDev(dmDevPath, true);
732     if (rc != 0) {
733         BEGET_LOGE("error 0x%x, create init dm dev", rc);
734         if (dmDevPath != NULL) {
735             free(dmDevPath);
736         }
737         goto exit;
738     }
739 
740     free(fsItem->deviceName);
741     fsItem->deviceName = dmDevPath;
742 
743 exit:
744     FsHvbDestoryVerityTarget(&target);
745 
746     return rc;
747 }
748 
FsExtHvbSetupHashtree(const char * devName,const char * partition,char ** outPath)749 static int FsExtHvbSetupHashtree(const char *devName, const char *partition, char **outPath)
750 {
751     int rc;
752     DmVerityTarget target = {0};
753     char *tmpDevName = NULL;
754     char *dmDevPath = NULL;
755     size_t devLen;
756 
757     FS_HVB_RETURN_ERR_IF_NULL(g_extVd);
758 
759     devLen = strnlen(devName, FS_HVB_MAX_PATH_LEN);
760     if (devLen >= FS_HVB_MAX_PATH_LEN) {
761         BEGET_LOGE("error, invalid devName");
762         return -1;
763     }
764     tmpDevName = malloc(devLen + 1);
765     if (tmpDevName == NULL) {
766         BEGET_LOGE("error, fail to malloc");
767         return -1;
768     }
769 
770     (void)memset_s(tmpDevName, devLen + 1, 0, devLen + 1);
771     if (memcpy_s(tmpDevName, devLen + 1, devName, devLen) != 0) {
772         free(tmpDevName);
773         BEGET_LOGE("error, fail to copy");
774         return -1;
775     }
776 
777     rc = FsExtHvbCreateVerityTarget(&target, tmpDevName, partition, g_extVd);
778     if (rc != 0) {
779         BEGET_LOGE("error 0x%x, create verity-table", rc);
780         goto exit;
781     }
782 
783     rc = FsDmCreateDevice(&dmDevPath, basename(tmpDevName), &target);
784     if (rc != 0) {
785         BEGET_LOGE("error 0x%x, create dm-verity", rc);
786         goto exit;
787     }
788 
789     rc = FsDmInitDmDev(dmDevPath, true);
790     if (rc != 0) {
791         BEGET_LOGE("error 0x%x, create init dm dev", rc);
792         if (dmDevPath != NULL) {
793             free(dmDevPath);
794         }
795         goto exit;
796     }
797 
798     *outPath = dmDevPath;
799 
800 exit:
801     FsHvbDestoryVerityTarget(&target);
802     free(tmpDevName);
803     return rc;
804 }
805 
FsHvbFinal(InitHvbType hvbType)806 int FsHvbFinal(InitHvbType hvbType)
807 {
808     struct hvb_verified_data **currVd = NULL;
809 
810     if (GetCurrVerifiedData(hvbType, &currVd) != HVB_OK) {
811         BEGET_LOGE("error GetCurrVerifiedData");
812         return -1;
813     }
814     if (*currVd != NULL) {
815         hvb_chain_verify_data_free(*currVd);
816         *currVd = NULL;
817     }
818 
819     return 0;
820 }
821 
FsHvbGetValueFromCmdLine(char * val,size_t size,const char * key)822 int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key)
823 {
824     FS_HVB_RETURN_ERR_IF_NULL(val);
825     FS_HVB_RETURN_ERR_IF_NULL(key);
826 
827     return GetExactParameterFromCmdLine(key, val, size);
828 }
829 
VerifyExtHvbImage(const char * devPath,const char * partition,char ** outPath)830 int VerifyExtHvbImage(const char *devPath, const char *partition, char **outPath)
831 {
832     int rc;
833     FS_HVB_RETURN_ERR_IF_NULL(devPath);
834     FS_HVB_RETURN_ERR_IF_NULL(partition);
835     FS_HVB_RETURN_ERR_IF_NULL(outPath);
836 
837     rc = FsHvbInit(EXT_HVB);
838     if (rc != 0) {
839         BEGET_LOGE("ext hvb error, ret=%d", rc);
840         goto exit;
841     }
842 
843     rc = FsExtHvbSetupHashtree(devPath, partition, outPath);
844     if (rc != 0) {
845         BEGET_LOGE("error, setup hashtree fail, ret=%d", rc);
846     }
847 
848 exit:
849     if (FsHvbFinal(EXT_HVB) != 0) {
850         BEGET_LOGE("final ext hvb error, ret=%d", rc);
851         return -1;
852     }
853     return rc;
854 }
855 
CheckAndGetExt4Size(const char * headerBuf,uint64_t * imageSize,const char * image)856 bool CheckAndGetExt4Size(const char *headerBuf, uint64_t *imageSize, const char* image)
857 {
858     ext4_super_block *superBlock = (ext4_super_block *)headerBuf;
859 
860     if (headerBuf == NULL || imageSize == NULL || image == NULL) {
861         BEGET_LOGE("param is error");
862         return false;
863     }
864 
865     if (superBlock->s_magic == EXT4_SUPER_MAGIC) {
866         *imageSize = (uint64_t)superBlock->s_blocks_count_lo * BLOCK_SIZE_UNIT;
867         BEGET_LOGI("%s is ext4:[block cout]: %d, [size]: 0x%lx", image,
868             superBlock->s_blocks_count_lo, *imageSize);
869         return true;
870     }
871     return false;
872 }
873 
CheckAndGetErofsSize(const char * headerBuf,uint64_t * imageSize,const char * image)874 bool CheckAndGetErofsSize(const char *headerBuf, uint64_t *imageSize, const char* image)
875 {
876     struct erofs_super_block *superBlock = (struct erofs_super_block *)headerBuf;
877 
878     if (headerBuf == NULL || imageSize == NULL || image == NULL) {
879         BEGET_LOGE("param is error");
880         return false;
881     }
882 
883     if (superBlock->magic == EROFS_SUPER_MAGIC) {
884         *imageSize = (uint64_t)superBlock->blocks * BLOCK_SIZE_UINT;
885         BEGET_LOGI("%s is erofs:[block cout]: %d, [size]: 0x%lx", image,
886             superBlock->blocks, *imageSize);
887         return true;
888     }
889     return false;
890 }
891 
CheckAndGetExtheaderSize(const int fd,uint64_t offset,uint64_t * imageSize,const char * image)892 bool CheckAndGetExtheaderSize(const int fd, uint64_t offset,
893                               uint64_t *imageSize, const char* image)
894 {
895     ExtheaderV1 header;
896     ssize_t nbytes;
897     if (fd < 0 || imageSize == NULL || image == NULL) {
898         BEGET_LOGE("param is error");
899         return false;
900     }
901 
902     if (lseek(fd, offset, SEEK_SET) < 0) {
903         BEGET_LOGE("lseek %s failed for offset 0x%lx", image, offset);
904         return false;
905     }
906 
907     nbytes = read(fd, &header, sizeof(header));
908     if (nbytes != sizeof(header)) {
909         BEGET_LOGE("read %s failed.", image);
910         return false;
911     }
912 
913     if (header.magicNumber != EXTHDR_MAGIC) {
914         BEGET_LOGW("%s extheader doesnt match, magic is 0x%lx", image, header.magicNumber);
915         return false;
916     }
917 
918     *imageSize = header.partSize;
919     return true;
920 }
921 
922 #ifdef __cplusplus
923 #if __cplusplus
924 }
925 #endif
926 #endif
927