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