1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
/*
* 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_PRIVATE_H__
#define __FEC_PRIVATE_H__
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <vector>
#include <crypto_utils/android_pubkey.h>
#include <fec/ecc.h>
#include <fec/io.h>
#include <openssl/obj_mac.h>
#include <openssl/sha.h>
#include <utils/Compat.h>
/* processing parameters */
#define WORK_MIN_THREADS 1
#define WORK_MAX_THREADS 64
/* verity parameters */
#define VERITY_CACHE_BLOCKS 4096
#define VERITY_NO_CACHE UINT64_MAX
/* verity definitions */
#define VERITY_METADATA_SIZE (8 * FEC_BLOCKSIZE)
#define VERITY_TABLE_ARGS 10 /* mandatory arguments */
#define VERITY_MIN_TABLE_SIZE (VERITY_TABLE_ARGS * 2) /* for a sanity check */
#define VERITY_MAX_TABLE_SIZE (VERITY_METADATA_SIZE - sizeof(verity_header))
/* verity header and metadata */
#define VERITY_MAGIC 0xB001B001
#define VERITY_MAGIC_DISABLE 0x46464F56
#define VERITY_VERSION 0
#define VERITY_TABLE_FIELDS 10
#define VERITY_TABLE_VERSION 1
struct verity_header {
uint32_t magic;
uint32_t version;
uint8_t signature[ANDROID_PUBKEY_MODULUS_SIZE];
uint32_t length;
};
/* file handle */
struct ecc_info {
bool valid;
int roots;
int rsn;
uint32_t size;
uint64_t blocks;
uint64_t rounds;
uint64_t start; /* offset in file */
};
struct hashtree_info {
// The number of the input data blocks to compute the hashtree.
uint64_t data_blocks;
// The offset of hashtree in the final image.
uint64_t hash_start;
// The hash concatenation of the input data, i.e. lowest level of the
// hashtree.
std::vector<uint8_t> hash_data;
std::vector<uint8_t> salt;
std::vector<uint8_t> zero_hash;
// Initialize the hashtree offsets and properties with the input parameters.
int initialize(uint64_t hash_start, uint64_t data_blocks,
const std::vector<uint8_t> &salt, int nid);
// Checks if the bytes in 'block' has the expected hash. And the 'index' is
// the block number of is the input block in the filesystem.
bool check_block_hash_with_index(uint64_t index, const uint8_t *block);
// Reads the verity hash tree, validates it against the root hash in `root',
// corrects errors if necessary, and copies valid data blocks for later use
// to 'hashtree'.
int verify_tree(const fec_handle *f, const uint8_t *root);
private:
bool ecc_read_hashes(fec_handle *f, uint64_t hash_offset, uint8_t *hash,
uint64_t data_offset, uint8_t *data);
// Computes the hash for FEC_BLOCKSIZE bytes from buffer 'block' and
// compares it to the expected value in 'expected'.
bool check_block_hash(const uint8_t *expected, const uint8_t *block);
// Computes the hash of 'block' and put the result in 'hash'.
int get_hash(const uint8_t *block, uint8_t *hash);
int nid_; // NID for the hash algorithm.
uint32_t digest_length_;
uint32_t padded_digest_length_;
};
struct verity_info {
bool disabled;
std::string table;
uint64_t metadata_start; /* offset in file */
hashtree_info hashtree;
verity_header header;
verity_header ecc_header;
};
struct fec_handle {
ecc_info ecc;
int fd;
int flags; /* additional flags passed to fec_open */
int mode; /* mode for open(2) */
pthread_mutex_t mutex;
uint64_t errors;
uint64_t data_size;
uint64_t pos;
uint64_t size;
verity_info verity;
hashtree_info hashtree() const {
return verity.hashtree;
}
};
/* I/O helpers */
extern bool raw_pread(int fd, void *buf, size_t count, uint64_t offset);
extern bool raw_pwrite(int fd, const void *buf, size_t count, uint64_t offset);
/* processing functions */
typedef ssize_t (*read_func)(fec_handle *f, uint8_t *dest, size_t count,
uint64_t offset, size_t *errors);
extern ssize_t process(fec_handle *f, uint8_t *buf, size_t count,
uint64_t offset, read_func func);
/* verity functions */
extern uint64_t verity_get_size(uint64_t file_size, uint32_t *verity_levels,
uint32_t *level_hashes,
uint32_t padded_digest_size);
extern int verity_parse_header(fec_handle *f, uint64_t offset);
/* helper macros */
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x), 0)
#define likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef stringify
#define __stringify(x) #x
#define stringify(x) __stringify(x)
#endif
/* warnings, errors, debug output */
#ifdef FEC_NO_KLOG
#define __log(func, type, format, args...) \
fprintf(stderr, "fec: <%d> " type ": %s: " format "\n", \
(int)syscall(SYS_gettid), __FUNCTION__, ##args)
#else
#include <cutils/klog.h>
#define __log(func, type, format, args...) \
KLOG_##func("fec", "<%d> " type ": %s: " format "\n", \
(int)syscall(SYS_gettid), __FUNCTION__, ##args)
#endif
#ifdef NDEBUG
#define debug(format, args...)
#else
#define debug(format, args...) __log(DEBUG, "debug", format, ##args)
#endif
#define warn(format, args...) __log(WARNING, "warning", format, ##args)
#define error(format, args...) __log(ERROR, "error", format, ##args)
#define check(p) \
if (unlikely(!(p))) { \
error("`%s' failed", #p); \
errno = EFAULT; \
return -1; \
}
#endif /* __FEC_PRIVATE_H__ */
|