1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <sysexits.h>
28
29 #include <android-base/properties.h>
30
31 #include <libavb_user/libavb_user.h>
32
33 namespace {
34
35 /* Prints program usage to |where|. */
usage(FILE * where,int,char * argv[])36 void usage(FILE* where, int /* argc */, char* argv[]) {
37 fprintf(where,
38 "%s - command-line tool for AVB.\n"
39 "\n"
40 "Usage:\n"
41 " %s COMMAND\n"
42 "\n"
43 "Commands:\n"
44 " %s get-verity - Prints whether verity is enabled in "
45 "current slot.\n"
46 " %s disable-verity - Disable verity in current slot.\n"
47 " %s enable-verity - Enable verity in current slot.\n"
48 " %s get-verification - Prints whether verification is enabled "
49 "in current slot.\n"
50 " %s disable-verification - Disable verification in current slot.\n"
51 " %s enable-verification - Enable verification in current slot.\n",
52 argv[0],
53 argv[0],
54 argv[0],
55 argv[0],
56 argv[0],
57 argv[0],
58 argv[0],
59 argv[0]);
60 }
61
62 /* Function to enable and disable verification. The |ops| parameter
63 * should be an |AvbOps| from libavb_user.
64 */
do_set_verification(AvbOps * ops,const std::string & ab_suffix,bool enable_verification)65 int do_set_verification(AvbOps* ops,
66 const std::string& ab_suffix,
67 bool enable_verification) {
68 bool verification_enabled;
69
70 if (!avb_user_verification_get(
71 ops, ab_suffix.c_str(), &verification_enabled)) {
72 fprintf(stderr, "Error getting whether verification is enabled.\n");
73 return EX_SOFTWARE;
74 }
75
76 if ((verification_enabled && enable_verification) ||
77 (!verification_enabled && !enable_verification)) {
78 fprintf(stdout,
79 "verification is already %s",
80 verification_enabled ? "enabled" : "disabled");
81 if (ab_suffix != "") {
82 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
83 }
84 fprintf(stdout, ".\n");
85 return EX_OK;
86 }
87
88 if (!avb_user_verification_set(ops, ab_suffix.c_str(), enable_verification)) {
89 fprintf(stderr, "Error setting verification.\n");
90 return EX_SOFTWARE;
91 }
92
93 fprintf(stdout,
94 "Successfully %s verification",
95 enable_verification ? "enabled" : "disabled");
96 if (ab_suffix != "") {
97 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
98 }
99 fprintf(stdout, ". Reboot the device for changes to take effect.\n");
100
101 return EX_OK;
102 }
103
104 /* Function to query if verification. The |ops| parameter should be an
105 * |AvbOps| from libavb_user.
106 */
do_get_verification(AvbOps * ops,const std::string & ab_suffix)107 int do_get_verification(AvbOps* ops, const std::string& ab_suffix) {
108 bool verification_enabled;
109
110 if (!avb_user_verification_get(
111 ops, ab_suffix.c_str(), &verification_enabled)) {
112 fprintf(stderr, "Error getting whether verification is enabled.\n");
113 return EX_SOFTWARE;
114 }
115
116 fprintf(stdout,
117 "verification is %s",
118 verification_enabled ? "enabled" : "disabled");
119 if (ab_suffix != "") {
120 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
121 }
122 fprintf(stdout, ".\n");
123
124 return EX_OK;
125 }
126
127 /* Function to enable and disable dm-verity. The |ops| parameter
128 * should be an |AvbOps| from libavb_user.
129 */
do_set_verity(AvbOps * ops,const std::string & ab_suffix,bool enable_verity)130 int do_set_verity(AvbOps* ops,
131 const std::string& ab_suffix,
132 bool enable_verity) {
133 bool verity_enabled;
134
135 if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) {
136 fprintf(stderr, "Error getting whether verity is enabled.\n");
137 return EX_SOFTWARE;
138 }
139
140 if ((verity_enabled && enable_verity) ||
141 (!verity_enabled && !enable_verity)) {
142 fprintf(stdout,
143 "verity is already %s",
144 verity_enabled ? "enabled" : "disabled");
145 if (ab_suffix != "") {
146 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
147 }
148 fprintf(stdout, ".\n");
149 return EX_OK;
150 }
151
152 if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) {
153 fprintf(stderr, "Error setting verity.\n");
154 return EX_SOFTWARE;
155 }
156
157 fprintf(
158 stdout, "Successfully %s verity", enable_verity ? "enabled" : "disabled");
159 if (ab_suffix != "") {
160 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
161 }
162 fprintf(stdout, ". Reboot the device for changes to take effect.\n");
163
164 return EX_OK;
165 }
166
167 /* Function to query if dm-verity is enabled. The |ops| parameter
168 * should be an |AvbOps| from libavb_user.
169 */
do_get_verity(AvbOps * ops,const std::string & ab_suffix)170 int do_get_verity(AvbOps* ops, const std::string& ab_suffix) {
171 bool verity_enabled;
172
173 if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) {
174 fprintf(stderr, "Error getting whether verity is enabled.\n");
175 return EX_SOFTWARE;
176 }
177
178 fprintf(stdout, "verity is %s", verity_enabled ? "enabled" : "disabled");
179 if (ab_suffix != "") {
180 fprintf(stdout, " on slot with suffix %s", ab_suffix.c_str());
181 }
182 fprintf(stdout, ".\n");
183
184 return EX_OK;
185 }
186
187 /* Helper function to get A/B suffix, if any. If the device isn't
188 * using A/B the empty string is returned. Otherwise either "_a",
189 * "_b", ... is returned.
190 *
191 * Note that since sometime in O androidboot.slot_suffix is deprecated
192 * and androidboot.slot should be used instead. Since bootloaders may
193 * be out of sync with the OS, we check both and for extra safety
194 * prepend a leading underscore if there isn't one already.
195 */
get_ab_suffix()196 std::string get_ab_suffix() {
197 std::string ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
198 if (ab_suffix == "") {
199 ab_suffix = android::base::GetProperty("ro.boot.slot", "");
200 }
201 if (ab_suffix.size() > 0 && ab_suffix[0] != '_') {
202 ab_suffix = std::string("_") + ab_suffix;
203 }
204 return ab_suffix;
205 }
206
207 } // namespace
208
main(int argc,char * argv[])209 int main(int argc, char* argv[]) {
210 int ret;
211 AvbOps* ops = nullptr;
212 std::string ab_suffix = get_ab_suffix();
213
214 if (argc < 2) {
215 usage(stderr, argc, argv);
216 ret = EX_USAGE;
217 goto out;
218 }
219
220 ops = avb_ops_user_new();
221 if (ops == nullptr) {
222 fprintf(stderr, "Error getting AVB ops.\n");
223 ret = EX_SOFTWARE;
224 goto out;
225 }
226
227 if (strcmp(argv[1], "disable-verity") == 0) {
228 ret = do_set_verity(ops, ab_suffix, false);
229 } else if (strcmp(argv[1], "enable-verity") == 0) {
230 ret = do_set_verity(ops, ab_suffix, true);
231 } else if (strcmp(argv[1], "get-verity") == 0) {
232 ret = do_get_verity(ops, ab_suffix);
233 } else if (strcmp(argv[1], "disable-verification") == 0) {
234 ret = do_set_verification(ops, ab_suffix, false);
235 } else if (strcmp(argv[1], "enable-verification") == 0) {
236 ret = do_set_verification(ops, ab_suffix, true);
237 } else if (strcmp(argv[1], "get-verification") == 0) {
238 ret = do_get_verification(ops, ab_suffix);
239 } else {
240 usage(stderr, argc, argv);
241 ret = EX_USAGE;
242 }
243
244 ret = EX_OK;
245 out:
246 if (ops != nullptr) {
247 avb_ops_user_free(ops);
248 }
249 return ret;
250 }
251