1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ___FEC_IO_H___
18#define ___FEC_IO_H___
19
20#include <fcntl.h>
21#include <inttypes.h>
22#include <limits.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <unistd.h>
27#include <mincrypt/rsa.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#ifndef SHA256_DIGEST_LENGTH
34#define SHA256_DIGEST_LENGTH 32
35#endif
36
37#define FEC_BLOCKSIZE 4096
38#define FEC_DEFAULT_ROOTS 2
39
40#define FEC_MAGIC 0xFECFECFE
41#define FEC_VERSION 0
42
43/* disk format for the header */
44struct fec_header {
45    uint32_t magic;
46    uint32_t version;
47    uint32_t size;
48    uint32_t roots;
49    uint32_t fec_size;
50    uint64_t inp_size;
51    uint8_t hash[SHA256_DIGEST_LENGTH];
52} __attribute__ ((packed));
53
54struct fec_status {
55    int flags;
56    int mode;
57    uint64_t errors;
58    uint64_t data_size;
59    uint64_t size;
60};
61
62struct fec_ecc_metadata {
63    bool valid;
64    uint32_t roots;
65    uint64_t blocks;
66    uint64_t rounds;
67    uint64_t start;
68};
69
70struct fec_verity_metadata {
71    bool disabled;
72    uint64_t data_size;
73    uint8_t signature[RSANUMBYTES];
74    uint8_t ecc_signature[RSANUMBYTES];
75    const char *table;
76    uint32_t table_length;
77};
78
79/* flags for fec_open */
80enum {
81    FEC_FS_EXT4 = 1 << 0,
82    FEC_FS_SQUASH = 1 << 1,
83    FEC_VERITY_DISABLE = 1 << 8
84};
85
86struct fec_handle;
87
88/* file access */
89extern int fec_open(struct fec_handle **f, const char *path, int mode,
90        int flags, int roots);
91
92extern int fec_close(struct fec_handle *f);
93
94extern int fec_verity_set_status(struct fec_handle *f, bool enabled);
95
96extern int fec_verity_get_metadata(struct fec_handle *f,
97        struct fec_verity_metadata *data);
98
99extern int fec_ecc_get_metadata(struct fec_handle *f,
100        struct fec_ecc_metadata *data);
101
102extern int fec_get_status(struct fec_handle *f, struct fec_status *s);
103
104extern int fec_seek(struct fec_handle *f, int64_t offset, int whence);
105
106extern ssize_t fec_read(struct fec_handle *f, void *buf, size_t count);
107
108extern ssize_t fec_pread(struct fec_handle *f, void *buf, size_t count,
109        uint64_t offset);
110
111#ifdef __cplusplus
112} /* extern "C" */
113
114#include <memory>
115#include <string>
116
117/* C++ wrappers for fec_handle and operations */
118namespace fec {
119    using handle = std::unique_ptr<fec_handle, decltype(&fec_close)>;
120
121    class io {
122    public:
123        io() : handle_(nullptr, fec_close) {}
124
125        io(const std::string& fn, int mode = O_RDONLY, int flags = 0,
126                int roots = FEC_DEFAULT_ROOTS) : handle_(nullptr, fec_close) {
127            open(fn, mode, flags, roots);
128        }
129
130        explicit operator bool() const {
131            return !!handle_;
132        }
133
134        bool open(const std::string& fn, int mode = O_RDONLY, int flags = 0,
135                    int roots = FEC_DEFAULT_ROOTS)
136        {
137            fec_handle *fh = nullptr;
138            int rc = fec_open(&fh, fn.c_str(), mode, flags, roots);
139            if (!rc) {
140                handle_.reset(fh);
141            }
142            return !rc;
143        }
144
145        bool close() {
146            return !fec_close(handle_.release());
147        }
148
149        bool seek(int64_t offset, int whence) {
150            return !fec_seek(handle_.get(), offset, whence);
151        }
152
153        ssize_t read(void *buf, size_t count) {
154            return fec_read(handle_.get(), buf, count);
155        }
156
157        ssize_t pread(void *buf, size_t count, uint64_t offset) {
158            return fec_pread(handle_.get(), buf, count, offset);
159        }
160
161        bool get_status(fec_status& status) {
162            return !fec_get_status(handle_.get(), &status);
163        }
164
165        bool get_verity_metadata(fec_verity_metadata& data) {
166            return !fec_verity_get_metadata(handle_.get(), &data);
167        }
168
169        bool has_verity() {
170            fec_verity_metadata data;
171            return get_verity_metadata(data);
172        }
173
174        bool get_ecc_metadata(fec_ecc_metadata& data) {
175            return !fec_ecc_get_metadata(handle_.get(), &data);
176        }
177
178        bool has_ecc() {
179            fec_ecc_metadata data;
180            return get_ecc_metadata(data) && data.valid;
181        }
182
183        bool set_verity_status(bool enabled) {
184            return !fec_verity_set_status(handle_.get(), enabled);
185        }
186
187    private:
188        handle handle_;
189    };
190}
191#endif
192
193#endif /* ___FEC_IO_H___ */
194