1/* 2 * Copyright (c) 2023-2024 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#include "fsverity_utils_helper.h" 16#include <common_defs.h> 17#include <fcntl.h> 18#include <fsverity_uapi.h> 19#include <sys/types.h> 20#include <unistd.h> 21#include "errcode.h" 22#include "file_helper.h" 23#include "log.h" 24 25namespace OHOS { 26namespace Security { 27namespace CodeSign { 28static constexpr int MAX_DIGEST_SIZE = 64; // size of sha512 29static constexpr int FSVERITY_HASH_PAGE_SIZE = 4096; 30static const char *FSVERITY_DIGEST_MAGIC = "FSVerity"; 31static constexpr uint32_t FSVERITY_DIGEST_MAGIC_LENGTH = 8; 32 33FsverityUtilsHelper &FsverityUtilsHelper::GetInstance() 34{ 35 static FsverityUtilsHelper singleFsverityUtilsHelper; 36 return singleFsverityUtilsHelper; 37} 38 39FsverityUtilsHelper::FsverityUtilsHelper() 40{ 41 Init(); 42} 43 44FsverityUtilsHelper::~FsverityUtilsHelper() {} 45 46void FsverityUtilsHelper::Init() 47{ 48 libfsverity_set_error_callback(ErrorMsgLogCallback); 49} 50 51void FsverityUtilsHelper::ErrorMsgLogCallback(const char *msg) 52{ 53 LOG_ERROR("fsverity_utils error = %{public}s", msg); 54} 55 56bool FsverityUtilsHelper::FormatDigest(libfsverity_digest *digest, uint8_t *buffer) 57{ 58 struct fsverity_formatted_digest *ret = reinterpret_cast<struct fsverity_formatted_digest *>(buffer); 59 if (memcpy_s(ret->magic, FSVERITY_DIGEST_MAGIC_LENGTH, FSVERITY_DIGEST_MAGIC, 60 FSVERITY_DIGEST_MAGIC_LENGTH) != EOK) { 61 return false; 62 } 63 ret->digest_algorithm = cpu_to_le16(digest->digest_algorithm); 64 ret->digest_size = cpu_to_le16(digest->digest_size); 65 if (memcpy_s(ret->digest, MAX_DIGEST_SIZE, digest->digest, digest->digest_size) != EOK) { 66 return false; 67 } 68 return true; 69} 70 71bool FsverityUtilsHelper::ComputeDigest(const char *path, struct libfsverity_digest **digest) 72{ 73 struct libfsverity_merkle_tree_params tree_params = { 74 .version = 1, 75 .hash_algorithm = FS_VERITY_HASH_ALG_SHA256, 76 .block_size = FSVERITY_HASH_PAGE_SIZE 77 }; 78 79 FileReader reader; 80 if (!reader.Open(path)) { 81 return false; 82 } 83 if (!reader.GetFileSize(&tree_params.file_size)) { 84 return false; 85 } 86 // compute digest by fsverity-utils and use callback to read data in file 87 if (libfsverity_compute_digest(&reader, FileReader::ReadFileCallback, &tree_params, digest)) { 88 LOG_ERROR("Compute digest failed."); 89 return false; 90 } 91 return true; 92} 93 94bool FsverityUtilsHelper::GenerateFormattedDigest(const char *path, ByteBuffer &digestBuffer) 95{ 96 LOG_INFO("GenerateFormattedDigest called."); 97 struct libfsverity_digest *digest = nullptr; 98 if (!ComputeDigest(path, &digest)) { 99 return false; 100 } 101 uint32_t digestLen = sizeof(struct fsverity_formatted_digest) + digest->digest_size; 102 if (!digestBuffer.Resize(digestLen)) { 103 free(digest); 104 return false; 105 } 106 bool ret = FormatDigest(digest, digestBuffer.GetBuffer()); 107 free(digest); 108 return ret; 109} 110} 111} 112}