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 
28 #include <crypto_utils/android_pubkey.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #ifndef SHA256_DIGEST_LENGTH
35 #define SHA256_DIGEST_LENGTH 32
36 #endif
37 
38 #define FEC_BLOCKSIZE 4096
39 #define FEC_DEFAULT_ROOTS 2
40 
41 #define FEC_MAGIC 0xFECFECFE
42 #define FEC_VERSION 0
43 
44 /* disk format for the header */
45 struct fec_header {
46     uint32_t magic;
47     uint32_t version;
48     uint32_t size;
49     uint32_t roots;
50     uint32_t fec_size;
51     uint64_t inp_size;
52     uint8_t hash[SHA256_DIGEST_LENGTH];
53 } __attribute__ ((packed));
54 
55 struct fec_status {
56     int flags;
57     int mode;
58     uint64_t errors;
59     uint64_t data_size;
60     uint64_t size;
61 };
62 
63 struct fec_ecc_metadata {
64     bool valid;
65     uint32_t roots;
66     uint64_t blocks;
67     uint64_t rounds;
68     uint64_t start;
69 };
70 
71 struct fec_verity_metadata {
72     bool disabled;
73     uint64_t data_size;
74     uint8_t signature[ANDROID_PUBKEY_MODULUS_SIZE];
75     uint8_t ecc_signature[ANDROID_PUBKEY_MODULUS_SIZE];
76     const char *table;
77     uint32_t table_length;
78 };
79 
80 /* flags for fec_open */
81 enum {
82     FEC_FS_EXT4 = 1 << 0,
83     FEC_FS_SQUASH = 1 << 1,
84     FEC_VERITY_DISABLE = 1 << 8
85 };
86 
87 struct fec_handle;
88 
89 /* file access */
90 extern int fec_open(struct fec_handle **f, const char *path, int mode,
91         int flags, int roots);
92 
93 extern int fec_close(struct fec_handle *f);
94 
95 extern int fec_verity_set_status(struct fec_handle *f, bool enabled);
96 
97 extern int fec_verity_get_metadata(struct fec_handle *f,
98         struct fec_verity_metadata *data);
99 
100 extern int fec_ecc_get_metadata(struct fec_handle *f,
101         struct fec_ecc_metadata *data);
102 
103 extern int fec_get_status(struct fec_handle *f, struct fec_status *s);
104 
105 extern int fec_seek(struct fec_handle *f, int64_t offset, int whence);
106 
107 extern ssize_t fec_read(struct fec_handle *f, void *buf, size_t count);
108 
109 extern ssize_t fec_pread(struct fec_handle *f, void *buf, size_t count,
110         uint64_t offset);
111 
112 #ifdef __cplusplus
113 } /* extern "C" */
114 
115 #include <memory>
116 #include <string>
117 
118 /* C++ wrappers for fec_handle and operations */
119 namespace fec {
120     using handle = std::unique_ptr<fec_handle, decltype(&fec_close)>;
121 
122     class io {
123     public:
io()124         io() : handle_(nullptr, fec_close) {}
125 
126         explicit io(const std::string& fn, int mode = O_RDONLY, int flags = 0,
handle_(nullptr,fec_close)127                 int roots = FEC_DEFAULT_ROOTS) : handle_(nullptr, fec_close) {
128             open(fn, mode, flags, roots);
129         }
130 
131         explicit operator bool() const {
132             return !!handle_;
133         }
134 
135         bool open(const std::string& fn, int mode = O_RDONLY, int flags = 0,
136                     int roots = FEC_DEFAULT_ROOTS)
137         {
138             fec_handle *fh = nullptr;
139             int rc = fec_open(&fh, fn.c_str(), mode, flags, roots);
140             if (!rc) {
141                 handle_.reset(fh);
142             }
143             return !rc;
144         }
145 
close()146         bool close() {
147             return !fec_close(handle_.release());
148         }
149 
seek(int64_t offset,int whence)150         bool seek(int64_t offset, int whence) {
151             return !fec_seek(handle_.get(), offset, whence);
152         }
153 
read(void * buf,size_t count)154         ssize_t read(void *buf, size_t count) {
155             return fec_read(handle_.get(), buf, count);
156         }
157 
pread(void * buf,size_t count,uint64_t offset)158         ssize_t pread(void *buf, size_t count, uint64_t offset) {
159             return fec_pread(handle_.get(), buf, count, offset);
160         }
161 
get_status(fec_status & status)162         bool get_status(fec_status& status) {
163             return !fec_get_status(handle_.get(), &status);
164         }
165 
get_verity_metadata(fec_verity_metadata & data)166         bool get_verity_metadata(fec_verity_metadata& data) {
167             return !fec_verity_get_metadata(handle_.get(), &data);
168         }
169 
has_verity()170         bool has_verity() {
171             fec_verity_metadata data;
172             return get_verity_metadata(data);
173         }
174 
get_ecc_metadata(fec_ecc_metadata & data)175         bool get_ecc_metadata(fec_ecc_metadata& data) {
176             return !fec_ecc_get_metadata(handle_.get(), &data);
177         }
178 
has_ecc()179         bool has_ecc() {
180             fec_ecc_metadata data;
181             return get_ecc_metadata(data) && data.valid;
182         }
183 
set_verity_status(bool enabled)184         bool set_verity_status(bool enabled) {
185             return !fec_verity_set_status(handle_.get(), enabled);
186         }
187 
188     private:
189         handle handle_;
190     };
191 }
192 #endif
193 
194 #endif /* ___FEC_IO_H___ */
195