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