xref: /aosp_15_r20/system/extras/verity/build_verity_tree_main.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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