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