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