You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
4.8 KiB
194 lines
4.8 KiB
/* |
|
* Copyright (C) 2015 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#ifndef ___FEC_IO_H___ |
|
#define ___FEC_IO_H___ |
|
|
|
#include <fcntl.h> |
|
#include <inttypes.h> |
|
#include <limits.h> |
|
#include <stdbool.h> |
|
#include <stdio.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
|
|
#include <crypto_utils/android_pubkey.h> |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
#ifndef SHA256_DIGEST_LENGTH |
|
#define SHA256_DIGEST_LENGTH 32 |
|
#endif |
|
|
|
#define FEC_BLOCKSIZE 4096 |
|
#define FEC_DEFAULT_ROOTS 2 |
|
|
|
#define FEC_MAGIC 0xFECFECFE |
|
#define FEC_VERSION 0 |
|
|
|
/* disk format for the header */ |
|
struct fec_header { |
|
uint32_t magic; |
|
uint32_t version; |
|
uint32_t size; |
|
uint32_t roots; |
|
uint32_t fec_size; |
|
uint64_t inp_size; |
|
uint8_t hash[SHA256_DIGEST_LENGTH]; |
|
} __attribute__ ((packed)); |
|
|
|
struct fec_status { |
|
int flags; |
|
int mode; |
|
uint64_t errors; |
|
uint64_t data_size; |
|
uint64_t size; |
|
}; |
|
|
|
struct fec_ecc_metadata { |
|
bool valid; |
|
uint32_t roots; |
|
uint64_t blocks; |
|
uint64_t rounds; |
|
uint64_t start; |
|
}; |
|
|
|
struct fec_verity_metadata { |
|
bool disabled; |
|
uint64_t data_size; |
|
uint8_t signature[ANDROID_PUBKEY_MODULUS_SIZE]; |
|
uint8_t ecc_signature[ANDROID_PUBKEY_MODULUS_SIZE]; |
|
const char *table; |
|
uint32_t table_length; |
|
}; |
|
|
|
/* flags for fec_open */ |
|
enum { |
|
FEC_FS_EXT4 = 1 << 0, |
|
FEC_FS_SQUASH = 1 << 1, |
|
FEC_VERITY_DISABLE = 1 << 8 |
|
}; |
|
|
|
struct fec_handle; |
|
|
|
/* file access */ |
|
extern int fec_open(struct fec_handle **f, const char *path, int mode, |
|
int flags, int roots); |
|
|
|
extern int fec_close(struct fec_handle *f); |
|
|
|
extern int fec_verity_set_status(struct fec_handle *f, bool enabled); |
|
|
|
extern int fec_verity_get_metadata(struct fec_handle *f, |
|
struct fec_verity_metadata *data); |
|
|
|
extern int fec_ecc_get_metadata(struct fec_handle *f, |
|
struct fec_ecc_metadata *data); |
|
|
|
extern int fec_get_status(struct fec_handle *f, struct fec_status *s); |
|
|
|
extern int fec_seek(struct fec_handle *f, int64_t offset, int whence); |
|
|
|
extern ssize_t fec_read(struct fec_handle *f, void *buf, size_t count); |
|
|
|
extern ssize_t fec_pread(struct fec_handle *f, void *buf, size_t count, |
|
uint64_t offset); |
|
|
|
#ifdef __cplusplus |
|
} /* extern "C" */ |
|
|
|
#include <memory> |
|
#include <string> |
|
|
|
/* C++ wrappers for fec_handle and operations */ |
|
namespace fec { |
|
using handle = std::unique_ptr<fec_handle, decltype(&fec_close)>; |
|
|
|
class io { |
|
public: |
|
io() : handle_(nullptr, fec_close) {} |
|
|
|
explicit io(const std::string& fn, int mode = O_RDONLY, int flags = 0, |
|
int roots = FEC_DEFAULT_ROOTS) : handle_(nullptr, fec_close) { |
|
open(fn, mode, flags, roots); |
|
} |
|
|
|
explicit operator bool() const { |
|
return !!handle_; |
|
} |
|
|
|
bool open(const std::string& fn, int mode = O_RDONLY, int flags = 0, |
|
int roots = FEC_DEFAULT_ROOTS) |
|
{ |
|
fec_handle *fh = nullptr; |
|
int rc = fec_open(&fh, fn.c_str(), mode, flags, roots); |
|
if (!rc) { |
|
handle_.reset(fh); |
|
} |
|
return !rc; |
|
} |
|
|
|
bool close() { |
|
return !fec_close(handle_.release()); |
|
} |
|
|
|
bool seek(int64_t offset, int whence) { |
|
return !fec_seek(handle_.get(), offset, whence); |
|
} |
|
|
|
ssize_t read(void *buf, size_t count) { |
|
return fec_read(handle_.get(), buf, count); |
|
} |
|
|
|
ssize_t pread(void *buf, size_t count, uint64_t offset) { |
|
return fec_pread(handle_.get(), buf, count, offset); |
|
} |
|
|
|
bool get_status(fec_status& status) { |
|
return !fec_get_status(handle_.get(), &status); |
|
} |
|
|
|
bool get_verity_metadata(fec_verity_metadata& data) { |
|
return !fec_verity_get_metadata(handle_.get(), &data); |
|
} |
|
|
|
bool has_verity() { |
|
fec_verity_metadata data; |
|
return get_verity_metadata(data); |
|
} |
|
|
|
bool get_ecc_metadata(fec_ecc_metadata& data) { |
|
return !fec_ecc_get_metadata(handle_.get(), &data); |
|
} |
|
|
|
bool has_ecc() { |
|
fec_ecc_metadata data; |
|
return get_ecc_metadata(data) && data.valid; |
|
} |
|
|
|
bool set_verity_status(bool enabled) { |
|
return !fec_verity_set_status(handle_.get(), enabled); |
|
} |
|
|
|
private: |
|
handle handle_; |
|
}; |
|
} |
|
#endif |
|
|
|
#endif /* ___FEC_IO_H___ */
|
|
|