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
16#ifndef CODE_SIGN_FSVERITY_UTILS_HELPER_H
17#define CODE_SIGN_FSVERITY_UTILS_HELPER_H
18
19#include <cerrno>
20#include <cstdint>
21#include <cstdlib>
22#include <cstring>
23#include <fcntl.h>
24#include <libfsverity.h>
25#include <sys/stat.h>
26#include <unistd.h>
27
28#include "errcode.h"
29#include "byte_buffer.h"
30#include "log.h"
31
32namespace OHOS {
33namespace Security {
34namespace CodeSign {
35class FsverityUtilsHelper {
36public:
37    static FsverityUtilsHelper &GetInstance();
38    bool GenerateFormattedDigest(const char *path, ByteBuffer &ret);
39    static void ErrorMsgLogCallback(const char *msg);
40
41private:
42    FsverityUtilsHelper();
43    ~FsverityUtilsHelper();
44
45    FsverityUtilsHelper(const FsverityUtilsHelper &source) = delete;
46    FsverityUtilsHelper &operator = (const FsverityUtilsHelper &source) = delete;
47
48    void Init();
49    bool ComputeDigest(const char *path, struct libfsverity_digest **digest);
50    bool FormatDigest(libfsverity_digest *digest, uint8_t *buffer);
51
52    class FileReader {
53    public:
54        bool Open(const char *path)
55        {
56            if (fd_ > 0) {
57                LOG_ERROR("File is already opened.");
58                return false;
59            }
60            fd_ = open(path, O_RDONLY);
61            if (fd_ <= 0) {
62                LOG_ERROR("Open file failed, path = %{public}s, errno = <%{public}d, %{public}s>",
63                    path, errno, strerror(errno));
64                return false;
65            }
66            return true;
67        }
68
69        bool GetFileSize(uint64_t *size)
70        {
71            struct stat st;
72            if (fstat(fd_, &st) != 0) {
73                LOG_ERROR("Stat file failed, errno = <%{public}d, %{public}s>",
74                    errno, strerror(errno));
75                return false;
76            }
77            *size = st.st_size;
78            return true;
79        }
80
81        ~FileReader()
82        {
83            if (fd_ > 0) {
84                close(fd_);
85                fd_ = -1;
86            }
87        }
88
89        static int ReadFileCallback(void *f, void *buf, size_t count)
90        {
91            FileReader *reader = static_cast<FileReader *>(f);
92            return reader->ReadBytes(static_cast<uint8_t *>(buf), count);
93        }
94
95    private:
96        int ReadBytes(uint8_t *buf, size_t count)
97        {
98            if (fd_ <= 0) {
99                return CS_ERR_FILE_READ;
100            }
101            while (count) {
102                ssize_t bytesRead = read(fd_, buf, count);
103                if (bytesRead <= 0) {
104                    return CS_ERR_FILE_READ;
105                }
106                buf += bytesRead;
107                count -= static_cast<size_t>(bytesRead);
108            }
109            return CS_SUCCESS;
110        }
111
112        int fd_ = -1;
113    };
114};
115}
116}
117}
118#endif