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