1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
18*288bf522SAndroid Build Coastguard Worker #include <getopt.h>
19*288bf522SAndroid Build Coastguard Worker #include <inttypes.h>
20*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
21*288bf522SAndroid Build Coastguard Worker #include <string.h>
22*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker #include <limits>
25*288bf522SAndroid Build Coastguard Worker #include <string>
26*288bf522SAndroid Build Coastguard Worker #include <vector>
27*288bf522SAndroid Build Coastguard Worker
28*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
29*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
30*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker #include "verity/build_verity_tree.h"
34*288bf522SAndroid Build Coastguard Worker
usage(void)35*288bf522SAndroid Build Coastguard Worker static void usage(void) {
36*288bf522SAndroid Build Coastguard Worker printf(
37*288bf522SAndroid Build Coastguard Worker "usage: build_verity_tree [ <options> ] -s <size> | <data> <verity>\n"
38*288bf522SAndroid Build Coastguard Worker "options:\n"
39*288bf522SAndroid Build Coastguard Worker " -a,--salt-str=<string> set salt to <string>\n"
40*288bf522SAndroid Build Coastguard Worker " -A,--salt-hex=<hex digits> set salt to <hex digits>\n"
41*288bf522SAndroid Build Coastguard Worker " -h show this help\n"
42*288bf522SAndroid Build Coastguard Worker " -s,--verity-size=<data size> print the size of the verity tree\n"
43*288bf522SAndroid Build Coastguard Worker " -v, enable verbose logging\n"
44*288bf522SAndroid Build Coastguard Worker " -S treat <data image> as a sparse file\n");
45*288bf522SAndroid Build Coastguard Worker }
46*288bf522SAndroid Build Coastguard Worker
main(int argc,char ** argv)47*288bf522SAndroid Build Coastguard Worker int main(int argc, char** argv) {
48*288bf522SAndroid Build Coastguard Worker constexpr size_t kBlockSize = 4096;
49*288bf522SAndroid Build Coastguard Worker
50*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char> salt;
51*288bf522SAndroid Build Coastguard Worker bool sparse = false;
52*288bf522SAndroid Build Coastguard Worker uint64_t calculate_size = 0;
53*288bf522SAndroid Build Coastguard Worker bool verbose = false;
54*288bf522SAndroid Build Coastguard Worker std::string hash_algorithm;
55*288bf522SAndroid Build Coastguard Worker
56*288bf522SAndroid Build Coastguard Worker while (1) {
57*288bf522SAndroid Build Coastguard Worker constexpr struct option long_options[] = {
58*288bf522SAndroid Build Coastguard Worker {"salt-str", required_argument, nullptr, 'a'},
59*288bf522SAndroid Build Coastguard Worker {"salt-hex", required_argument, nullptr, 'A'},
60*288bf522SAndroid Build Coastguard Worker {"help", no_argument, nullptr, 'h'},
61*288bf522SAndroid Build Coastguard Worker {"sparse", no_argument, nullptr, 'S'},
62*288bf522SAndroid Build Coastguard Worker {"verity-size", required_argument, nullptr, 's'},
63*288bf522SAndroid Build Coastguard Worker {"verbose", no_argument, nullptr, 'v'},
64*288bf522SAndroid Build Coastguard Worker {"hash-algorithm", required_argument, nullptr, 0},
65*288bf522SAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0}};
66*288bf522SAndroid Build Coastguard Worker int option_index;
67*288bf522SAndroid Build Coastguard Worker int c = getopt_long(argc, argv, "a:A:hSs:v", long_options, &option_index);
68*288bf522SAndroid Build Coastguard Worker if (c < 0) {
69*288bf522SAndroid Build Coastguard Worker break;
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker
72*288bf522SAndroid Build Coastguard Worker switch (c) {
73*288bf522SAndroid Build Coastguard Worker case 'a':
74*288bf522SAndroid Build Coastguard Worker salt.clear();
75*288bf522SAndroid Build Coastguard Worker salt.insert(salt.end(), optarg, &optarg[strlen(optarg)]);
76*288bf522SAndroid Build Coastguard Worker break;
77*288bf522SAndroid Build Coastguard Worker case 'A':
78*288bf522SAndroid Build Coastguard Worker if (!HashTreeBuilder::ParseBytesArrayFromString(optarg, &salt)) {
79*288bf522SAndroid Build Coastguard Worker return 1;
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker break;
82*288bf522SAndroid Build Coastguard Worker case 'h':
83*288bf522SAndroid Build Coastguard Worker usage();
84*288bf522SAndroid Build Coastguard Worker return 1;
85*288bf522SAndroid Build Coastguard Worker case 'S':
86*288bf522SAndroid Build Coastguard Worker sparse = true;
87*288bf522SAndroid Build Coastguard Worker break;
88*288bf522SAndroid Build Coastguard Worker case 's': {
89*288bf522SAndroid Build Coastguard Worker if (!android::base::ParseUint(optarg, &calculate_size,
90*288bf522SAndroid Build Coastguard Worker std::numeric_limits<uint64_t>::max())) {
91*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid input size: " << optarg;
92*288bf522SAndroid Build Coastguard Worker return 1;
93*288bf522SAndroid Build Coastguard Worker }
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Worker } break;
96*288bf522SAndroid Build Coastguard Worker case 'v':
97*288bf522SAndroid Build Coastguard Worker verbose = true;
98*288bf522SAndroid Build Coastguard Worker break;
99*288bf522SAndroid Build Coastguard Worker case 0: {
100*288bf522SAndroid Build Coastguard Worker std::string option = long_options[option_index].name;
101*288bf522SAndroid Build Coastguard Worker if (option == "hash-algorithm") {
102*288bf522SAndroid Build Coastguard Worker hash_algorithm = optarg;
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker } break;
105*288bf522SAndroid Build Coastguard Worker case '?':
106*288bf522SAndroid Build Coastguard Worker usage();
107*288bf522SAndroid Build Coastguard Worker return 1;
108*288bf522SAndroid Build Coastguard Worker default:
109*288bf522SAndroid Build Coastguard Worker abort();
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker
113*288bf522SAndroid Build Coastguard Worker argc -= optind;
114*288bf522SAndroid Build Coastguard Worker argv += optind;
115*288bf522SAndroid Build Coastguard Worker
116*288bf522SAndroid Build Coastguard Worker auto hash_function = hash_algorithm.empty()
117*288bf522SAndroid Build Coastguard Worker ? EVP_sha256()
118*288bf522SAndroid Build Coastguard Worker : HashTreeBuilder::HashFunction(hash_algorithm);
119*288bf522SAndroid Build Coastguard Worker if (hash_function == nullptr) {
120*288bf522SAndroid Build Coastguard Worker return 1;
121*288bf522SAndroid Build Coastguard Worker }
122*288bf522SAndroid Build Coastguard Worker HashTreeBuilder builder(kBlockSize, hash_function);
123*288bf522SAndroid Build Coastguard Worker
124*288bf522SAndroid Build Coastguard Worker if (calculate_size) {
125*288bf522SAndroid Build Coastguard Worker if (argc != 0) {
126*288bf522SAndroid Build Coastguard Worker usage();
127*288bf522SAndroid Build Coastguard Worker return 1;
128*288bf522SAndroid Build Coastguard Worker }
129*288bf522SAndroid Build Coastguard Worker
130*288bf522SAndroid Build Coastguard Worker uint64_t tree_size = builder.CalculateSize(calculate_size);
131*288bf522SAndroid Build Coastguard Worker printf("%" PRIu64 "\n", tree_size);
132*288bf522SAndroid Build Coastguard Worker return 0;
133*288bf522SAndroid Build Coastguard Worker }
134*288bf522SAndroid Build Coastguard Worker
135*288bf522SAndroid Build Coastguard Worker if (argc != 2) {
136*288bf522SAndroid Build Coastguard Worker usage();
137*288bf522SAndroid Build Coastguard Worker return 1;
138*288bf522SAndroid Build Coastguard Worker }
139*288bf522SAndroid Build Coastguard Worker
140*288bf522SAndroid Build Coastguard Worker if (salt.empty()) {
141*288bf522SAndroid Build Coastguard Worker salt.resize(builder.hash_size());
142*288bf522SAndroid Build Coastguard Worker
143*288bf522SAndroid Build Coastguard Worker android::base::unique_fd random_fd(open("/dev/urandom", O_RDONLY));
144*288bf522SAndroid Build Coastguard Worker if (random_fd < 0) {
145*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to open /dev/urandom";
146*288bf522SAndroid Build Coastguard Worker return 1;
147*288bf522SAndroid Build Coastguard Worker }
148*288bf522SAndroid Build Coastguard Worker
149*288bf522SAndroid Build Coastguard Worker ssize_t ret = read(random_fd, salt.data(), salt.size());
150*288bf522SAndroid Build Coastguard Worker if (ret != static_cast<ssize_t>(salt.size())) {
151*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to read " << salt.size()
152*288bf522SAndroid Build Coastguard Worker << " bytes from /dev/urandom: " << ret;
153*288bf522SAndroid Build Coastguard Worker return 1;
154*288bf522SAndroid Build Coastguard Worker }
155*288bf522SAndroid Build Coastguard Worker }
156*288bf522SAndroid Build Coastguard Worker
157*288bf522SAndroid Build Coastguard Worker if (!generate_verity_tree(argv[0], argv[1], &builder, salt, kBlockSize,
158*288bf522SAndroid Build Coastguard Worker sparse, verbose)) {
159*288bf522SAndroid Build Coastguard Worker return 1;
160*288bf522SAndroid Build Coastguard Worker }
161*288bf522SAndroid Build Coastguard Worker
162*288bf522SAndroid Build Coastguard Worker // Output the root hash and the salt.
163*288bf522SAndroid Build Coastguard Worker std::string root_hash_string =
164*288bf522SAndroid Build Coastguard Worker HashTreeBuilder::BytesArrayToString(builder.root_hash());
165*288bf522SAndroid Build Coastguard Worker std::string salt_string = HashTreeBuilder::BytesArrayToString(salt);
166*288bf522SAndroid Build Coastguard Worker printf("%s %s\n", root_hash_string.c_str(), salt_string.c_str());
167*288bf522SAndroid Build Coastguard Worker
168*288bf522SAndroid Build Coastguard Worker return 0;
169*288bf522SAndroid Build Coastguard Worker }
170