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
30 extern "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 */
44 struct 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 };
53 
54 struct fec_status {
55     int flags;
56     int mode;
57     uint64_t errors;
58     uint64_t data_size;
59     uint64_t size;
60 };
61 
62 struct fec_ecc_metadata {
63     bool valid;
64     uint32_t roots;
65     uint64_t blocks;
66     uint64_t rounds;
67     uint64_t start;
68 };
69 
70 struct 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 */
80 enum {
81     FEC_FS_EXT4 = 1 << 0,
82     FEC_FS_SQUASH = 1 << 1,
83     FEC_VERITY_DISABLE = 1 << 8
84 };
85 
86 struct fec_handle;
87 
88 /* file access */
89 extern int fec_open(struct fec_handle **f, const char *path, int mode,
90         int flags, int roots);
91 
92 extern int fec_close(struct fec_handle *f);
93 
94 extern int fec_verity_set_status(struct fec_handle *f, bool enabled);
95 
96 extern int fec_verity_get_metadata(struct fec_handle *f,
97         struct fec_verity_metadata *data);
98 
99 extern int fec_ecc_get_metadata(struct fec_handle *f,
100         struct fec_ecc_metadata *data);
101 
102 extern int fec_get_status(struct fec_handle *f, struct fec_status *s);
103 
104 extern int fec_seek(struct fec_handle *f, int64_t offset, int whence);
105 
106 extern ssize_t fec_read(struct fec_handle *f, void *buf, size_t count);
107 
108 extern 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 */
118 namespace fec {
119     using handle = std::unique_ptr<fec_handle, decltype(&fec_close)>;
120 
121     class io {
122     public:
io()123         io() : handle_(nullptr, fec_close) {}
124 
125         io(const std::string& fn, int mode = O_RDONLY, int flags = 0,
handle_(nullptr,fec_close)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 
close()145         bool close() {
146             return !fec_close(handle_.release());
147         }
148 
seek(int64_t offset,int whence)149         bool seek(int64_t offset, int whence) {
150             return !fec_seek(handle_.get(), offset, whence);
151         }
152 
read(void * buf,size_t count)153         ssize_t read(void *buf, size_t count) {
154             return fec_read(handle_.get(), buf, count);
155         }
156 
pread(void * buf,size_t count,uint64_t offset)157         ssize_t pread(void *buf, size_t count, uint64_t offset) {
158             return fec_pread(handle_.get(), buf, count, offset);
159         }
160 
get_status(fec_status & status)161         bool get_status(fec_status& status) {
162             return !fec_get_status(handle_.get(), &status);
163         }
164 
get_verity_metadata(fec_verity_metadata & data)165         bool get_verity_metadata(fec_verity_metadata& data) {
166             return !fec_verity_get_metadata(handle_.get(), &data);
167         }
168 
has_verity()169         bool has_verity() {
170             fec_verity_metadata data;
171             return get_verity_metadata(data);
172         }
173 
get_ecc_metadata(fec_ecc_metadata & data)174         bool get_ecc_metadata(fec_ecc_metadata& data) {
175             return !fec_ecc_get_metadata(handle_.get(), &data);
176         }
177 
has_ecc()178         bool has_ecc() {
179             fec_ecc_metadata data;
180             return get_ecc_metadata(data) && data.valid;
181         }
182 
set_verity_status(bool enabled)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