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 } __attribute__ ((packed)); 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: 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