• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <libgen.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/mount.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <time.h>
30 #include <unistd.h>
31 
32 #include <android-base/file.h>
33 #include <android-base/properties.h>
34 #include <android-base/strings.h>
35 #include <android-base/unique_fd.h>
36 #include <crypto_utils/android_pubkey.h>
37 #include <cutils/properties.h>
38 #include <fs_mgr/file_wait.h>
39 #include <libdm/dm.h>
40 #include <logwrap/logwrap.h>
41 #include <openssl/obj_mac.h>
42 #include <openssl/rsa.h>
43 #include <openssl/sha.h>
44 
45 #include "fec/io.h"
46 
47 #include "fs_mgr.h"
48 #include "fs_mgr_dm_linear.h"
49 #include "fs_mgr_priv.h"
50 
51 // Realistically, this file should be part of the android::fs_mgr namespace;
52 using namespace android::fs_mgr;
53 
54 #define VERITY_TABLE_RSA_KEY "/verity_key"
55 #define VERITY_TABLE_HASH_IDX 8
56 #define VERITY_TABLE_SALT_IDX 9
57 
58 #define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
59 #define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
60 #define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
61 
62 #define VERITY_TABLE_OPT_FEC_FORMAT \
63     "use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 \
64     " fec_roots %u " VERITY_TABLE_OPT_IGNZERO
65 #define VERITY_TABLE_OPT_FEC_ARGS 9
66 
67 #define METADATA_MAGIC 0x01564c54
68 #define METADATA_TAG_MAX_LENGTH 63
69 #define METADATA_EOD "eod"
70 
71 #define VERITY_LASTSIG_TAG "verity_lastsig"
72 
73 #define VERITY_STATE_TAG "verity_state"
74 #define VERITY_STATE_HEADER 0x83c0ae9d
75 #define VERITY_STATE_VERSION 1
76 
77 #define VERITY_KMSG_RESTART "dm-verity device corrupted"
78 #define VERITY_KMSG_BUFSIZE 1024
79 
80 #define READ_BUF_SIZE 4096
81 
82 #define __STRINGIFY(x) #x
83 #define STRINGIFY(x) __STRINGIFY(x)
84 
85 struct verity_state {
86     uint32_t header;
87     uint32_t version;
88     int32_t mode;
89 };
90 
91 extern struct fs_info info;
92 
load_key(const char * path)93 static RSA *load_key(const char *path)
94 {
95     uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
96 
97     auto f = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path, "re"), fclose};
98     if (!f) {
99         LERROR << "Can't open " << path;
100         return nullptr;
101     }
102 
103     if (!fread(key_data, sizeof(key_data), 1, f.get())) {
104         LERROR << "Could not read key!";
105         return nullptr;
106     }
107 
108     RSA* key = nullptr;
109     if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) {
110         LERROR << "Could not parse key!";
111         return nullptr;
112     }
113 
114     return key;
115 }
116 
verify_table(const uint8_t * signature,size_t signature_size,const char * table,uint32_t table_length)117 static int verify_table(const uint8_t *signature, size_t signature_size,
118         const char *table, uint32_t table_length)
119 {
120     RSA *key;
121     uint8_t hash_buf[SHA256_DIGEST_LENGTH];
122     int retval = -1;
123 
124     // Hash the table
125     SHA256((uint8_t*)table, table_length, hash_buf);
126 
127     // Now get the public key from the keyfile
128     key = load_key(VERITY_TABLE_RSA_KEY);
129     if (!key) {
130         LERROR << "Couldn't load verity keys";
131         goto out;
132     }
133 
134     // verify the result
135     if (!RSA_verify(NID_sha256, hash_buf, sizeof(hash_buf), signature,
136                     signature_size, key)) {
137         LERROR << "Couldn't verify table";
138         goto out;
139     }
140 
141     retval = 0;
142 
143 out:
144     RSA_free(key);
145     return retval;
146 }
147 
verify_verity_signature(const struct fec_verity_metadata & verity)148 static int verify_verity_signature(const struct fec_verity_metadata& verity)
149 {
150     if (verify_table(verity.signature, sizeof(verity.signature),
151             verity.table, verity.table_length) == 0 ||
152         verify_table(verity.ecc_signature, sizeof(verity.ecc_signature),
153             verity.table, verity.table_length) == 0) {
154         return 0;
155     }
156 
157     return -1;
158 }
159 
invalidate_table(char * table,size_t table_length)160 static int invalidate_table(char *table, size_t table_length)
161 {
162     size_t n = 0;
163     size_t idx = 0;
164     size_t cleared = 0;
165 
166     while (n < table_length) {
167         if (table[n++] == ' ') {
168             ++idx;
169         }
170 
171         if (idx != VERITY_TABLE_HASH_IDX && idx != VERITY_TABLE_SALT_IDX) {
172             continue;
173         }
174 
175         while (n < table_length && table[n] != ' ') {
176             table[n++] = '0';
177         }
178 
179         if (++cleared == 2) {
180             return 0;
181         }
182     }
183 
184     return -1;
185 }
186 
187 struct verity_table_params {
188     char *table;
189     int mode;
190     struct fec_ecc_metadata ecc;
191     const char *ecc_dev;
192 };
193 
194 typedef bool (*format_verity_table_func)(char *buf, const size_t bufsize,
195         const struct verity_table_params *params);
196 
format_verity_table(char * buf,const size_t bufsize,const struct verity_table_params * params)197 static bool format_verity_table(char *buf, const size_t bufsize,
198         const struct verity_table_params *params)
199 {
200     const char *mode_flag = NULL;
201     int res = -1;
202 
203     if (params->mode == VERITY_MODE_RESTART) {
204         mode_flag = VERITY_TABLE_OPT_RESTART;
205     } else if (params->mode == VERITY_MODE_LOGGING) {
206         mode_flag = VERITY_TABLE_OPT_LOGGING;
207     }
208 
209     if (params->ecc.valid) {
210         if (mode_flag) {
211             res = snprintf(buf, bufsize,
212                     "%s %u %s " VERITY_TABLE_OPT_FEC_FORMAT,
213                     params->table, 1 + VERITY_TABLE_OPT_FEC_ARGS, mode_flag, params->ecc_dev,
214                     params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
215         } else {
216             res = snprintf(buf, bufsize,
217                     "%s %u " VERITY_TABLE_OPT_FEC_FORMAT,
218                     params->table, VERITY_TABLE_OPT_FEC_ARGS, params->ecc_dev,
219                     params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
220         }
221     } else if (mode_flag) {
222         res = snprintf(buf, bufsize, "%s 2 " VERITY_TABLE_OPT_IGNZERO " %s", params->table,
223                     mode_flag);
224     } else {
225         res = snprintf(buf, bufsize, "%s 1 " VERITY_TABLE_OPT_IGNZERO, params->table);
226     }
227 
228     if (res < 0 || (size_t)res >= bufsize) {
229         LERROR << "Error building verity table; insufficient buffer size?";
230         return false;
231     }
232 
233     return true;
234 }
235 
format_legacy_verity_table(char * buf,const size_t bufsize,const struct verity_table_params * params)236 static bool format_legacy_verity_table(char *buf, const size_t bufsize,
237         const struct verity_table_params *params)
238 {
239     int res;
240 
241     if (params->mode == VERITY_MODE_EIO) {
242         res = strlcpy(buf, params->table, bufsize);
243     } else {
244         res = snprintf(buf, bufsize, "%s %d", params->table, params->mode);
245     }
246 
247     if (res < 0 || (size_t)res >= bufsize) {
248         LERROR << "Error building verity table; insufficient buffer size?";
249         return false;
250     }
251 
252     return true;
253 }
254 
load_verity_table(android::dm::DeviceMapper & dm,const std::string & name,uint64_t device_size,const struct verity_table_params * params,format_verity_table_func format)255 static int load_verity_table(android::dm::DeviceMapper& dm, const std::string& name,
256                              uint64_t device_size, const struct verity_table_params* params,
257                              format_verity_table_func format) {
258     android::dm::DmTable table;
259     table.set_readonly(true);
260 
261     char buffer[DM_BUF_SIZE];
262     if (!format(buffer, sizeof(buffer), params)) {
263         LERROR << "Failed to format verity parameters";
264         return -1;
265     }
266 
267     android::dm::DmTargetVerityString target(0, device_size / 512, buffer);
268     if (!table.AddTarget(std::make_unique<decltype(target)>(target))) {
269         LERROR << "Failed to add verity target";
270         return -1;
271     }
272     if (!dm.CreateDevice(name, table)) {
273         LERROR << "Failed to create verity device \"" << name << "\"";
274         return -1;
275     }
276     return 0;
277 }
278 
read_partition(const char * path,uint64_t size)279 static int read_partition(const char *path, uint64_t size)
280 {
281     char buf[READ_BUF_SIZE];
282     ssize_t size_read;
283     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
284 
285     if (fd == -1) {
286         PERROR << "Failed to open " << path;
287         return -errno;
288     }
289 
290     while (size) {
291         size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
292         if (size_read == -1) {
293             PERROR << "Error in reading partition " << path;
294             return -errno;
295         }
296         size -= size_read;
297     }
298 
299     return 0;
300 }
301 
fs_mgr_load_verity_state(int * mode)302 bool fs_mgr_load_verity_state(int* mode) {
303     // unless otherwise specified, use EIO mode.
304     *mode = VERITY_MODE_EIO;
305 
306     // The bootloader communicates verity mode via the kernel commandline
307     std::string verity_mode;
308     if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
309         return false;
310     }
311 
312     if (verity_mode == "enforcing") {
313         *mode = VERITY_MODE_DEFAULT;
314     } else if (verity_mode == "logging") {
315         *mode = VERITY_MODE_LOGGING;
316     }
317 
318     return true;
319 }
320 
321 // Update the verity table using the actual block device path.
322 // Two cases:
323 // Case-1: verity table is shared for devices with different by-name prefix.
324 // Example:
325 //   verity table token:       /dev/block/bootdevice/by-name/vendor
326 //   blk_device-1 (non-A/B):   /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor
327 //   blk_device-2 (A/B):       /dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor_a
328 //
329 // Case-2: append A/B suffix in the verity table.
330 // Example:
331 //   verity table token: /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor
332 //   blk_device:         /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor_a
update_verity_table_blk_device(const std::string & blk_device,char ** table,bool slot_select)333 static void update_verity_table_blk_device(const std::string& blk_device, char** table,
334                                            bool slot_select) {
335     bool updated = false;
336     std::string result, ab_suffix;
337     auto tokens = android::base::Split(*table, " ");
338 
339     // If slot_select is set, it means blk_device is already updated with ab_suffix.
340     if (slot_select) ab_suffix = fs_mgr_get_slot_suffix();
341 
342     for (const auto& token : tokens) {
343         std::string new_token;
344         if (android::base::StartsWith(token, "/dev/block/")) {
345             if (token == blk_device) return;  // no need to update if they're already the same.
346             std::size_t found1 = blk_device.find("by-name");
347             std::size_t found2 = token.find("by-name");
348             if (found1 != std::string::npos && found2 != std::string::npos &&
349                 blk_device.substr(found1) == token.substr(found2) + ab_suffix) {
350                 new_token = blk_device;
351             }
352         }
353 
354         if (!new_token.empty()) {
355             updated = true;
356             LINFO << "Verity table: updated block device from '" << token << "' to '" << new_token
357                   << "'";
358         } else {
359             new_token = token;
360         }
361 
362         if (result.empty()) {
363             result = new_token;
364         } else {
365             result += " " + new_token;
366         }
367     }
368 
369     if (!updated) {
370         return;
371     }
372 
373     free(*table);
374     *table = strdup(result.c_str());
375 }
376 
377 // prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
378 // mount. The 'wait_for_verity_dev' parameter makes this function wait for the
379 // verity device to get created before return
fs_mgr_setup_verity(FstabEntry * entry,bool wait_for_verity_dev)380 int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) {
381     int retval = FS_MGR_SETUP_VERITY_FAIL;
382     int fd = -1;
383     std::string verity_blk_name;
384     struct fec_handle *f = NULL;
385     struct fec_verity_metadata verity;
386     struct verity_table_params params = { .table = NULL };
387 
388     const std::string mount_point(basename(entry->mount_point.c_str()));
389     bool verified_at_boot = false;
390 
391     android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
392 
393     if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) <
394         0) {
395         PERROR << "Failed to open '" << entry->blk_device << "'";
396         return retval;
397     }
398 
399     // read verity metadata
400     if (fec_verity_get_metadata(f, &verity) < 0) {
401         PERROR << "Failed to get verity metadata '" << entry->blk_device << "'";
402         // Allow verity disabled when the device is unlocked without metadata
403         if (fs_mgr_is_device_unlocked()) {
404             retval = FS_MGR_SETUP_VERITY_SKIPPED;
405             LWARNING << "Allow invalid metadata when the device is unlocked";
406         }
407         goto out;
408     }
409 
410 #ifdef ALLOW_ADBD_DISABLE_VERITY
411     if (verity.disabled) {
412         retval = FS_MGR_SETUP_VERITY_DISABLED;
413         LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG/ENG";
414         goto out;
415     }
416 #endif
417 
418     // read ecc metadata
419     if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
420         params.ecc.valid = false;
421     }
422 
423     params.ecc_dev = entry->blk_device.c_str();
424 
425     if (!fs_mgr_load_verity_state(&params.mode)) {
426         /* if accessing or updating the state failed, switch to the default
427          * safe mode. This makes sure the device won't end up in an endless
428          * restart loop, and no corrupted data will be exposed to userspace
429          * without a warning. */
430         params.mode = VERITY_MODE_EIO;
431     }
432 
433     if (!verity.table) {
434         goto out;
435     }
436 
437     params.table = strdup(verity.table);
438     if (!params.table) {
439         goto out;
440     }
441 
442     // verify the signature on the table
443     if (verify_verity_signature(verity) < 0) {
444         // Allow signature verification error when the device is unlocked
445         if (fs_mgr_is_device_unlocked()) {
446             retval = FS_MGR_SETUP_VERITY_SKIPPED;
447             LWARNING << "Allow signature verification error when the device is unlocked";
448             goto out;
449         }
450         if (params.mode == VERITY_MODE_LOGGING) {
451             // the user has been warned, allow mounting without dm-verity
452             retval = FS_MGR_SETUP_VERITY_SKIPPED;
453             goto out;
454         }
455 
456         // invalidate root hash and salt to trigger device-specific recovery
457         if (invalidate_table(params.table, verity.table_length) < 0) {
458             goto out;
459         }
460     }
461 
462     LINFO << "Enabling dm-verity for " << mount_point.c_str()
463           << " (mode " << params.mode << ")";
464 
465     // Update the verity params using the actual block device path
466     update_verity_table_blk_device(entry->blk_device, &params.table,
467                                    entry->fs_mgr_flags.slot_select);
468 
469     // load the verity mapping table
470     if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
471         goto loaded;
472     }
473 
474     if (params.ecc.valid) {
475         // kernel may not support error correction, try without
476         LINFO << "Disabling error correction for " << mount_point.c_str();
477         params.ecc.valid = false;
478 
479         if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
480             goto loaded;
481         }
482     }
483 
484     // try the legacy format for backwards compatibility
485     if (load_verity_table(dm, mount_point, verity.data_size, &params, format_legacy_verity_table) ==
486         0) {
487         goto loaded;
488     }
489 
490     if (params.mode != VERITY_MODE_EIO) {
491         // as a last resort, EIO mode should always be supported
492         LINFO << "Falling back to EIO mode for " << mount_point.c_str();
493         params.mode = VERITY_MODE_EIO;
494 
495         if (load_verity_table(dm, mount_point, verity.data_size, &params,
496                               format_legacy_verity_table) == 0) {
497             goto loaded;
498         }
499     }
500 
501     LERROR << "Failed to load verity table for " << mount_point.c_str();
502     goto out;
503 
504 loaded:
505     if (!dm.GetDmDevicePathByName(mount_point, &verity_blk_name)) {
506         LERROR << "Couldn't get verity device number!";
507         goto out;
508     }
509 
510     // mark the underlying block device as read-only
511     fs_mgr_set_blk_ro(entry->blk_device);
512 
513     // Verify the entire partition in one go
514     // If there is an error, allow it to mount as a normal verity partition.
515     if (entry->fs_mgr_flags.verify_at_boot) {
516         LINFO << "Verifying partition " << entry->blk_device << " at boot";
517         int err = read_partition(verity_blk_name.c_str(), verity.data_size);
518         if (!err) {
519             LINFO << "Verified verity partition " << entry->blk_device << " at boot";
520             verified_at_boot = true;
521         }
522     }
523 
524     // assign the new verity block device as the block device
525     if (!verified_at_boot) {
526         entry->blk_device = verity_blk_name;
527     } else if (!dm.DeleteDevice(mount_point)) {
528         LERROR << "Failed to remove verity device " << mount_point.c_str();
529         goto out;
530     }
531 
532     // make sure we've set everything up properly
533     if (wait_for_verity_dev && !WaitForFile(entry->blk_device, 1s)) {
534         goto out;
535     }
536 
537     retval = FS_MGR_SETUP_VERITY_SUCCESS;
538 
539 out:
540     if (fd != -1) {
541         close(fd);
542     }
543 
544     fec_close(f);
545     free(params.table);
546 
547     return retval;
548 }
549 
fs_mgr_teardown_verity(FstabEntry * entry)550 bool fs_mgr_teardown_verity(FstabEntry* entry) {
551     const std::string mount_point(basename(entry->mount_point.c_str()));
552     if (!android::fs_mgr::UnmapDevice(mount_point)) {
553         return false;
554     }
555     LINFO << "Unmapped verity device " << mount_point;
556     return true;
557 }
558