summaryrefslogtreecommitdiff
path: root/libfec/fec_private.h
blob: 0c633223e1e732f96bc71393d6cba76db4a90ba8 (plain)
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
203
204
205
206
207
208
209
210
/*
 * 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 <android-base/threads.h>
#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 quick validation */
#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 avb_info {
    bool valid = false;
    std::vector<uint8_t> vbmeta;
    hashtree_info hashtree;
};

struct fec_handle {
    ecc_info ecc;
    int fd;
    int flags; /* additional flags passed to fec_open */
    int mode;  /* mode for open(2) */
    uint64_t errors;
    uint64_t data_size;
    uint64_t pos;
    uint64_t size;
    // TODO(xunchang) switch to std::optional
    verity_info verity;
    avb_info avb;

    hashtree_info hashtree() const {
        return avb.valid ? avb.hashtree : 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: <%" PRIu64 "> " type ": %s: " format "\n", \
            android::base::GetThreadId(), __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__ */