fs_mgr_verity.c revision 72f0d92c722447e0c87cfe765516a7352db3d51a
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 <inttypes.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <unistd.h> 22#include <fcntl.h> 23#include <ctype.h> 24#include <sys/mount.h> 25#include <sys/stat.h> 26#include <errno.h> 27#include <sys/types.h> 28#include <sys/wait.h> 29#include <libgen.h> 30#include <time.h> 31 32#include <private/android_filesystem_config.h> 33#include <cutils/properties.h> 34#include <logwrap/logwrap.h> 35 36#include "mincrypt/rsa.h" 37#include "mincrypt/sha.h" 38#include "mincrypt/sha256.h" 39 40#include "ext4_sb.h" 41 42#include "fs_mgr_priv.h" 43#include "fs_mgr_priv_verity.h" 44 45#define VERITY_METADATA_SIZE 32768 46#define VERITY_TABLE_RSA_KEY "/verity_key" 47 48extern struct fs_info info; 49 50static RSAPublicKey *load_key(char *path) 51{ 52 FILE *f; 53 RSAPublicKey *key; 54 55 key = malloc(sizeof(RSAPublicKey)); 56 if (!key) { 57 ERROR("Can't malloc key\n"); 58 return NULL; 59 } 60 61 f = fopen(path, "r"); 62 if (!f) { 63 ERROR("Can't open '%s'\n", path); 64 free(key); 65 return NULL; 66 } 67 68 if (!fread(key, sizeof(*key), 1, f)) { 69 ERROR("Could not read key!"); 70 fclose(f); 71 free(key); 72 return NULL; 73 } 74 75 if (key->len != RSANUMWORDS) { 76 ERROR("Invalid key length %d\n", key->len); 77 fclose(f); 78 free(key); 79 return NULL; 80 } 81 82 fclose(f); 83 return key; 84} 85 86static int verify_table(char *signature, char *table, int table_length) 87{ 88 RSAPublicKey *key; 89 uint8_t hash_buf[SHA256_DIGEST_SIZE]; 90 int retval = -1; 91 92 // Hash the table 93 SHA256_hash((uint8_t*)table, table_length, hash_buf); 94 95 // Now get the public key from the keyfile 96 key = load_key(VERITY_TABLE_RSA_KEY); 97 if (!key) { 98 ERROR("Couldn't load verity keys"); 99 goto out; 100 } 101 102 // verify the result 103 if (!RSA_verify(key, 104 (uint8_t*) signature, 105 RSANUMBYTES, 106 (uint8_t*) hash_buf, 107 SHA256_DIGEST_SIZE)) { 108 ERROR("Couldn't verify table."); 109 goto out; 110 } 111 112 retval = 0; 113 114out: 115 free(key); 116 return retval; 117} 118 119static int get_target_device_size(char *blk_device, uint64_t *device_size) 120{ 121 int data_device; 122 struct ext4_super_block sb; 123 struct fs_info info = {0}; 124 125 data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)); 126 if (data_device == -1) { 127 ERROR("Error opening block device (%s)", strerror(errno)); 128 return -1; 129 } 130 131 if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) { 132 ERROR("Error seeking to superblock"); 133 TEMP_FAILURE_RETRY(close(data_device)); 134 return -1; 135 } 136 137 if (TEMP_FAILURE_RETRY(read(data_device, &sb, sizeof(sb))) != sizeof(sb)) { 138 ERROR("Error reading superblock"); 139 TEMP_FAILURE_RETRY(close(data_device)); 140 return -1; 141 } 142 143 ext4_parse_sb(&sb, &info); 144 *device_size = info.len; 145 146 TEMP_FAILURE_RETRY(close(data_device)); 147 return 0; 148} 149 150static int read_verity_metadata(char *block_device, char **signature, char **table) 151{ 152 unsigned magic_number; 153 unsigned table_length; 154 uint64_t device_length; 155 int protocol_version; 156 int device; 157 int retval = FS_MGR_SETUP_VERITY_FAIL; 158 *signature = 0; 159 *table = 0; 160 161 device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC)); 162 if (device == -1) { 163 ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno)); 164 goto out; 165 } 166 167 // find the start of the verity metadata 168 if (get_target_device_size(block_device, &device_length) < 0) { 169 ERROR("Could not get target device size.\n"); 170 goto out; 171 } 172 if (TEMP_FAILURE_RETRY(lseek64(device, device_length, SEEK_SET)) < 0) { 173 ERROR("Could not seek to start of verity metadata block.\n"); 174 goto out; 175 } 176 177 // check the magic number 178 if (TEMP_FAILURE_RETRY(read(device, &magic_number, sizeof(magic_number))) != 179 sizeof(magic_number)) { 180 ERROR("Couldn't read magic number!\n"); 181 goto out; 182 } 183 184#ifdef ALLOW_ADBD_DISABLE_VERITY 185 if (magic_number == VERITY_METADATA_MAGIC_DISABLE) { 186 retval = FS_MGR_SETUP_VERITY_DISABLED; 187 INFO("Attempt to cleanly disable verity - only works in USERDEBUG"); 188 goto out; 189 } 190#endif 191 192 if (magic_number != VERITY_METADATA_MAGIC_NUMBER) { 193 ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", 194 device_length); 195 goto out; 196 } 197 198 // check the protocol version 199 if (TEMP_FAILURE_RETRY(read(device, &protocol_version, 200 sizeof(protocol_version))) != sizeof(protocol_version)) { 201 ERROR("Couldn't read verity metadata protocol version!\n"); 202 goto out; 203 } 204 if (protocol_version != 0) { 205 ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version); 206 goto out; 207 } 208 209 // get the signature 210 *signature = (char*) malloc(RSANUMBYTES); 211 if (!*signature) { 212 ERROR("Couldn't allocate memory for signature!\n"); 213 goto out; 214 } 215 if (TEMP_FAILURE_RETRY(read(device, *signature, RSANUMBYTES)) != RSANUMBYTES) { 216 ERROR("Couldn't read signature from verity metadata!\n"); 217 goto out; 218 } 219 220 // get the size of the table 221 if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) != 222 sizeof(table_length)) { 223 ERROR("Couldn't get the size of the verity table from metadata!\n"); 224 goto out; 225 } 226 227 // get the table + null terminator 228 *table = malloc(table_length + 1); 229 if (!*table) { 230 ERROR("Couldn't allocate memory for verity table!\n"); 231 goto out; 232 } 233 if (TEMP_FAILURE_RETRY(read(device, *table, table_length)) != 234 (ssize_t)table_length) { 235 ERROR("Couldn't read the verity table from metadata!\n"); 236 goto out; 237 } 238 239 (*table)[table_length] = 0; 240 retval = FS_MGR_SETUP_VERITY_SUCCESS; 241 242out: 243 if (device != -1) 244 TEMP_FAILURE_RETRY(close(device)); 245 246 if (retval != FS_MGR_SETUP_VERITY_SUCCESS) { 247 free(*table); 248 free(*signature); 249 *table = 0; 250 *signature = 0; 251 } 252 253 return retval; 254} 255 256static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags) 257{ 258 memset(io, 0, DM_BUF_SIZE); 259 io->data_size = DM_BUF_SIZE; 260 io->data_start = sizeof(struct dm_ioctl); 261 io->version[0] = 4; 262 io->version[1] = 0; 263 io->version[2] = 0; 264 io->flags = flags | DM_READONLY_FLAG; 265 if (name) { 266 strlcpy(io->name, name, sizeof(io->name)); 267 } 268} 269 270static int create_verity_device(struct dm_ioctl *io, char *name, int fd) 271{ 272 verity_ioctl_init(io, name, 1); 273 if (ioctl(fd, DM_DEV_CREATE, io)) { 274 ERROR("Error creating device mapping (%s)", strerror(errno)); 275 return -1; 276 } 277 return 0; 278} 279 280static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name) 281{ 282 verity_ioctl_init(io, name, 0); 283 if (ioctl(fd, DM_DEV_STATUS, io)) { 284 ERROR("Error fetching verity device number (%s)", strerror(errno)); 285 return -1; 286 } 287 int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 288 if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) { 289 ERROR("Error getting verity block device name (%s)", strerror(errno)); 290 return -1; 291 } 292 return 0; 293} 294 295static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table) 296{ 297 char *verity_params; 298 char *buffer = (char*) io; 299 uint64_t device_size = 0; 300 301 if (get_target_device_size(blockdev, &device_size) < 0) { 302 return -1; 303 } 304 305 verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG); 306 307 struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 308 309 // set tgt arguments here 310 io->target_count = 1; 311 tgt->status=0; 312 tgt->sector_start=0; 313 tgt->length=device_size/512; 314 strcpy(tgt->target_type, "verity"); 315 316 // build the verity params here 317 verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 318 if (sprintf(verity_params, "%s", table) < 0) { 319 return -1; 320 } 321 322 // set next target boundary 323 verity_params += strlen(verity_params) + 1; 324 verity_params = (char*) (((unsigned long)verity_params + 7) & ~8); 325 tgt->next = verity_params - buffer; 326 327 // send the ioctl to load the verity table 328 if (ioctl(fd, DM_TABLE_LOAD, io)) { 329 ERROR("Error loading verity table (%s)", strerror(errno)); 330 return -1; 331 } 332 333 return 0; 334} 335 336static int resume_verity_table(struct dm_ioctl *io, char *name, int fd) 337{ 338 verity_ioctl_init(io, name, 0); 339 if (ioctl(fd, DM_DEV_SUSPEND, io)) { 340 ERROR("Error activating verity device (%s)", strerror(errno)); 341 return -1; 342 } 343 return 0; 344} 345 346static int test_access(char *device) { 347 int tries = 25; 348 while (tries--) { 349 if (!access(device, F_OK) || errno != ENOENT) { 350 return 0; 351 } 352 usleep(40 * 1000); 353 } 354 return -1; 355} 356 357static int set_verified_property(char *name) { 358 int ret; 359 char *key; 360 ret = asprintf(&key, "partition.%s.verified", name); 361 if (ret < 0) { 362 ERROR("Error formatting verified property"); 363 return ret; 364 } 365 ret = PROP_NAME_MAX - strlen(key); 366 if (ret < 0) { 367 ERROR("Verified property name is too long"); 368 return -1; 369 } 370 ret = property_set(key, "1"); 371 if (ret < 0) 372 ERROR("Error setting verified property %s: %d", key, ret); 373 free(key); 374 return ret; 375} 376 377int fs_mgr_setup_verity(struct fstab_rec *fstab) { 378 379 int retval = FS_MGR_SETUP_VERITY_FAIL; 380 int fd = -1; 381 382 char *verity_blk_name = 0; 383 char *verity_table = 0; 384 char *verity_table_signature = 0; 385 386 char buffer[DM_BUF_SIZE]; 387 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 388 char *mount_point = basename(fstab->mount_point); 389 390 // set the dm_ioctl flags 391 io->flags |= 1; 392 io->target_count = 1; 393 394 // check to ensure that the verity device is ext4 395 // TODO: support non-ext4 filesystems 396 if (strcmp(fstab->fs_type, "ext4")) { 397 ERROR("Cannot verify non-ext4 device (%s)", fstab->fs_type); 398 return retval; 399 } 400 401 // read the verity block at the end of the block device 402 // send error code up the chain so we can detect attempts to disable verity 403 retval = read_verity_metadata(fstab->blk_device, 404 &verity_table_signature, 405 &verity_table); 406 if (retval < 0) { 407 goto out; 408 } 409 410 retval = FS_MGR_SETUP_VERITY_FAIL; 411 412 // get the device mapper fd 413 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 414 ERROR("Error opening device mapper (%s)", strerror(errno)); 415 goto out; 416 } 417 418 // create the device 419 if (create_verity_device(io, mount_point, fd) < 0) { 420 ERROR("Couldn't create verity device!"); 421 goto out; 422 } 423 424 // get the name of the device file 425 if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) { 426 ERROR("Couldn't get verity device number!"); 427 goto out; 428 } 429 430 // verify the signature on the table 431 if (verify_table(verity_table_signature, 432 verity_table, 433 strlen(verity_table)) < 0) { 434 goto out; 435 } 436 437 // load the verity mapping table 438 if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) { 439 goto out; 440 } 441 442 // activate the device 443 if (resume_verity_table(io, mount_point, fd) < 0) { 444 goto out; 445 } 446 447 // assign the new verity block device as the block device 448 free(fstab->blk_device); 449 fstab->blk_device = verity_blk_name; 450 verity_blk_name = 0; 451 452 // make sure we've set everything up properly 453 if (test_access(fstab->blk_device) < 0) { 454 goto out; 455 } 456 457 // set the property indicating that the partition is verified 458 retval = set_verified_property(mount_point); 459 460out: 461 if (fd != -1) { 462 close(fd); 463 } 464 465 free(verity_table); 466 free(verity_table_signature); 467 free(verity_blk_name); 468 469 return retval; 470} 471