• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 <stdlib.h>
19 #include <android-base/strings.h>
20 #include "fec_private.h"
21 
22 /* converts a hex nibble into an int */
hextobin(char c)23 static inline int hextobin(char c)
24 {
25     if (c >= '0' && c <= '9') {
26         return c - '0';
27     } else if (c >= 'a' && c <= 'f') {
28         return c - 'a' + 10;
29     } else {
30         errno = EINVAL;
31         return -1;
32     }
33 }
34 
35 /* converts a hex string `src' of `size' characters to binary and copies the
36    the result into `dst' */
parse_hex(uint8_t * dst,uint32_t size,const char * src)37 static int parse_hex(uint8_t *dst, uint32_t size, const char *src)
38 {
39     int l, h;
40 
41     check(dst);
42     check(src);
43     check(2 * size == strlen(src));
44 
45     while (size) {
46         h = hextobin(tolower(*src++));
47         l = hextobin(tolower(*src++));
48 
49         check(l >= 0);
50         check(h >= 0);
51 
52         *dst++ = (h << 4) | l;
53         --size;
54     }
55 
56     return 0;
57 }
58 
59 /* parses a 64-bit unsigned integer from string `src' into `dst' and if
60    `maxval' is >0, checks that `dst' <= `maxval' */
parse_uint64(const char * src,uint64_t maxval,uint64_t * dst)61 static int parse_uint64(const char *src, uint64_t maxval, uint64_t *dst)
62 {
63     char *end;
64     unsigned long long int value;
65 
66     check(src);
67     check(dst);
68 
69     errno = 0;
70     value = strtoull(src, &end, 0);
71 
72     if (*src == '\0' || *end != '\0' ||
73             (errno == ERANGE && value == ULLONG_MAX)) {
74         errno = EINVAL;
75         return -1;
76     }
77 
78     if (maxval && value > maxval) {
79         errno = EINVAL;
80         return -1;
81     }
82 
83    *dst = (uint64_t)value;
84     return 0;
85 }
86 
87 /* computes the size of verity hash tree for `file_size' bytes and returns the
88    number of hash tree levels in `verity_levels,' and the number of hashes per
89    level in `level_hashes', if the parameters are non-NULL */
verity_get_size(uint64_t file_size,uint32_t * verity_levels,uint32_t * level_hashes)90 uint64_t verity_get_size(uint64_t file_size, uint32_t *verity_levels,
91         uint32_t *level_hashes)
92 {
93     /* we assume a known metadata size, 4 KiB block size, and SHA-256 to avoid
94        relying on disk content */
95 
96     uint32_t level = 0;
97     uint64_t total = 0;
98     uint64_t hashes = file_size / FEC_BLOCKSIZE;
99 
100     do {
101         if (level_hashes) {
102             level_hashes[level] = hashes;
103         }
104 
105         hashes = fec_div_round_up(hashes * SHA256_DIGEST_LENGTH, FEC_BLOCKSIZE);
106         total += hashes;
107 
108         ++level;
109     } while (hashes > 1);
110 
111     if (verity_levels) {
112         *verity_levels = level;
113     }
114 
115     return total * FEC_BLOCKSIZE;
116 }
117 
118 /* computes a SHA-256 salted with `f->verity.salt' from a FEC_BLOCKSIZE byte
119    buffer `block', and copies the hash to `hash' */
verity_hash(fec_handle * f,const uint8_t * block,uint8_t * hash)120 static inline int verity_hash(fec_handle *f, const uint8_t *block,
121         uint8_t *hash)
122 {
123     SHA256_CTX ctx;
124     SHA256_Init(&ctx);
125 
126     check(f);
127     check(f->verity.salt);
128     SHA256_Update(&ctx, f->verity.salt, f->verity.salt_size);
129 
130     check(block);
131     SHA256_Update(&ctx, block, FEC_BLOCKSIZE);
132 
133     check(hash);
134     SHA256_Final(hash, &ctx);
135     return 0;
136 }
137 
138 /* computes a verity hash for FEC_BLOCKSIZE bytes from buffer `block' and
139    compares it to the expected value in `expected' */
verity_check_block(fec_handle * f,const uint8_t * expected,const uint8_t * block)140 bool verity_check_block(fec_handle *f, const uint8_t *expected,
141         const uint8_t *block)
142 {
143     check(f);
144     check(block);
145 
146     uint8_t hash[SHA256_DIGEST_LENGTH];
147 
148     if (unlikely(verity_hash(f, block, hash) == -1)) {
149         error("failed to hash");
150         return false;
151     }
152 
153     check(expected);
154     return !memcmp(expected, hash, SHA256_DIGEST_LENGTH);
155 }
156 
157 /* reads a verity hash and the corresponding data block using error correction,
158    if available */
ecc_read_hashes(fec_handle * f,uint64_t hash_offset,uint8_t * hash,uint64_t data_offset,uint8_t * data)159 static bool ecc_read_hashes(fec_handle *f, uint64_t hash_offset,
160         uint8_t *hash, uint64_t data_offset, uint8_t *data)
161 {
162     check(f);
163 
164     if (hash && fec_pread(f, hash, SHA256_DIGEST_LENGTH, hash_offset) !=
165                     SHA256_DIGEST_LENGTH) {
166         error("failed to read hash tree: offset %" PRIu64 ": %s", hash_offset,
167             strerror(errno));
168         return false;
169     }
170 
171     check(data);
172 
173     if (fec_pread(f, data, FEC_BLOCKSIZE, data_offset) != FEC_BLOCKSIZE) {
174         error("failed to read hash tree: data_offset %" PRIu64 ": %s",
175             data_offset, strerror(errno));
176         return false;
177     }
178 
179     return true;
180 }
181 
182 /* reads the verity hash tree, validates it against the root hash in `root',
183    corrects errors if necessary, and copies valid data blocks for later use
184    to `f->verity.hash' */
verify_tree(fec_handle * f,const uint8_t * root)185 static int verify_tree(fec_handle *f, const uint8_t *root)
186 {
187     uint8_t data[FEC_BLOCKSIZE];
188     uint8_t hash[SHA256_DIGEST_LENGTH];
189 
190     check(f);
191     check(root);
192 
193     verity_info *v = &f->verity;
194     uint32_t levels = 0;
195 
196     /* calculate the size and the number of levels in the hash tree */
197     v->hash_size =
198         verity_get_size(v->data_blocks * FEC_BLOCKSIZE, &levels, NULL);
199 
200     check(v->hash_start < UINT64_MAX - v->hash_size);
201     check(v->hash_start + v->hash_size <= f->data_size);
202 
203     uint64_t hash_offset = v->hash_start;
204     uint64_t data_offset = hash_offset + FEC_BLOCKSIZE;
205 
206     v->hash_data_offset = data_offset;
207 
208     /* validate the root hash */
209     if (!raw_pread(f, data, FEC_BLOCKSIZE, hash_offset) ||
210             !verity_check_block(f, root, data)) {
211         /* try to correct */
212         if (!ecc_read_hashes(f, 0, NULL, hash_offset, data) ||
213                 !verity_check_block(f, root, data)) {
214             error("root hash invalid");
215             return -1;
216         } else if (f->mode & O_RDWR &&
217                     !raw_pwrite(f, data, FEC_BLOCKSIZE, hash_offset)) {
218             error("failed to rewrite the root block: %s", strerror(errno));
219             return -1;
220         }
221     }
222 
223     debug("root hash valid");
224 
225     /* calculate the number of hashes on each level */
226     uint32_t hashes[levels];
227 
228     verity_get_size(v->data_blocks * FEC_BLOCKSIZE, NULL, hashes);
229 
230     /* calculate the size and offset for the data hashes */
231     for (uint32_t i = 1; i < levels; ++i) {
232         uint32_t blocks = hashes[levels - i];
233         debug("%u hash blocks on level %u", blocks, levels - i);
234 
235         v->hash_data_offset = data_offset;
236         v->hash_data_blocks = blocks;
237 
238         data_offset += blocks * FEC_BLOCKSIZE;
239     }
240 
241     check(v->hash_data_blocks);
242     check(v->hash_data_blocks <= v->hash_size / FEC_BLOCKSIZE);
243 
244     check(v->hash_data_offset);
245     check(v->hash_data_offset <=
246         UINT64_MAX - (v->hash_data_blocks * FEC_BLOCKSIZE));
247     check(v->hash_data_offset < f->data_size);
248     check(v->hash_data_offset + v->hash_data_blocks * FEC_BLOCKSIZE <=
249         f->data_size);
250 
251     /* copy data hashes to memory in case they are corrupted, so we don't
252        have to correct them every time they are needed */
253     std::unique_ptr<uint8_t[]> data_hashes(
254        new (std::nothrow) uint8_t[f->verity.hash_data_blocks * FEC_BLOCKSIZE]);
255 
256     if (!data_hashes) {
257         errno = ENOMEM;
258         return -1;
259     }
260 
261     /* validate the rest of the hash tree */
262     data_offset = hash_offset + FEC_BLOCKSIZE;
263 
264     for (uint32_t i = 1; i < levels; ++i) {
265         uint32_t blocks = hashes[levels - i];
266 
267         for (uint32_t j = 0; j < blocks; ++j) {
268             /* ecc reads are very I/O intensive, so read raw hash tree and do
269                error correcting only if it doesn't validate */
270             if (!raw_pread(f, hash, SHA256_DIGEST_LENGTH,
271                     hash_offset + j * SHA256_DIGEST_LENGTH) ||
272                 !raw_pread(f, data, FEC_BLOCKSIZE,
273                     data_offset + j * FEC_BLOCKSIZE)) {
274                 error("failed to read hashes: %s", strerror(errno));
275                 return -1;
276             }
277 
278             if (!verity_check_block(f, hash, data)) {
279                 /* try to correct */
280                 if (!ecc_read_hashes(f,
281                         hash_offset + j * SHA256_DIGEST_LENGTH, hash,
282                         data_offset + j * FEC_BLOCKSIZE, data) ||
283                     !verity_check_block(f, hash, data)) {
284                     error("invalid hash tree: hash_offset %" PRIu64 ", "
285                         "data_offset %" PRIu64 ", block %u",
286                         hash_offset, data_offset, j);
287                     return -1;
288                 }
289 
290                 /* update the corrected blocks to the file if we are in r/w
291                    mode */
292                 if (f->mode & O_RDWR) {
293                     if (!raw_pwrite(f, hash, SHA256_DIGEST_LENGTH,
294                             hash_offset + j * SHA256_DIGEST_LENGTH) ||
295                         !raw_pwrite(f, data, FEC_BLOCKSIZE,
296                             data_offset + j * FEC_BLOCKSIZE)) {
297                         error("failed to write hashes: %s", strerror(errno));
298                         return -1;
299                     }
300                 }
301             }
302 
303             if (blocks == v->hash_data_blocks) {
304                 memcpy(data_hashes.get() + j * FEC_BLOCKSIZE, data,
305                     FEC_BLOCKSIZE);
306             }
307         }
308 
309         hash_offset = data_offset;
310         data_offset += blocks * FEC_BLOCKSIZE;
311     }
312 
313     debug("valid");
314 
315     if (v->hash) {
316         delete[] v->hash;
317         v->hash = NULL;
318     }
319 
320     v->hash = data_hashes.release();
321     return 0;
322 }
323 
324 /* reads, corrects and parses the verity table, validates parameters, and if
325    `f->flags' does not have `FEC_VERITY_DISABLE' set, calls `verify_tree' to
326    load and validate the hash tree */
parse_table(fec_handle * f,uint64_t offset,uint32_t size,bool useecc)327 static int parse_table(fec_handle *f, uint64_t offset, uint32_t size, bool useecc)
328 {
329     check(f);
330     check(size >= VERITY_MIN_TABLE_SIZE);
331     check(size <= VERITY_MAX_TABLE_SIZE);
332 
333     debug("offset = %" PRIu64 ", size = %u", offset, size);
334 
335     verity_info *v = &f->verity;
336     std::unique_ptr<char[]> table(new (std::nothrow) char[size + 1]);
337 
338     if (!table) {
339         errno = ENOMEM;
340         return -1;
341     }
342 
343     if (!useecc) {
344         if (!raw_pread(f, table.get(), size, offset)) {
345             error("failed to read verity table: %s", strerror(errno));
346             return -1;
347         }
348     } else if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) {
349         error("failed to ecc read verity table: %s", strerror(errno));
350         return -1;
351     }
352 
353     table[size] = '\0';
354     debug("verity table: '%s'", table.get());
355 
356     int i = 0;
357     std::unique_ptr<uint8_t[]> salt;
358     uint8_t root[SHA256_DIGEST_LENGTH];
359 
360     auto tokens = android::base::Split(table.get(), " ");
361 
362     for (const auto& token : tokens) {
363         switch (i++) {
364         case 0: /* version */
365             if (token != stringify(VERITY_TABLE_VERSION)) {
366                 error("unsupported verity table version: %s", token.c_str());
367                 return -1;
368             }
369             break;
370         case 3: /* data_block_size */
371         case 4: /* hash_block_size */
372             /* assume 4 KiB block sizes for everything */
373             if (token != stringify(FEC_BLOCKSIZE)) {
374                 error("unsupported verity block size: %s", token.c_str());
375                 return -1;
376             }
377             break;
378         case 5: /* num_data_blocks */
379             if (parse_uint64(token.c_str(), f->data_size / FEC_BLOCKSIZE,
380                     &v->data_blocks) == -1) {
381                 error("invalid number of verity data blocks: %s",
382                     token.c_str());
383                 return -1;
384             }
385             break;
386         case 6: /* hash_start_block */
387             if (parse_uint64(token.c_str(), f->data_size / FEC_BLOCKSIZE,
388                     &v->hash_start) == -1) {
389                 error("invalid verity hash start block: %s", token.c_str());
390                 return -1;
391             }
392 
393             v->hash_start *= FEC_BLOCKSIZE;
394             break;
395         case 7: /* algorithm */
396             if (token != "sha256") {
397                 error("unsupported verity hash algorithm: %s", token.c_str());
398                 return -1;
399             }
400             break;
401         case 8: /* digest */
402             if (parse_hex(root, sizeof(root), token.c_str()) == -1) {
403                 error("invalid verity root hash: %s", token.c_str());
404                 return -1;
405             }
406             break;
407         case 9: /* salt */
408             v->salt_size = token.size();
409             check(v->salt_size % 2 == 0);
410             v->salt_size /= 2;
411 
412             salt.reset(new (std::nothrow) uint8_t[v->salt_size]);
413 
414             if (!salt) {
415                 errno = ENOMEM;
416                 return -1;
417             }
418 
419             if (parse_hex(salt.get(), v->salt_size, token.c_str()) == -1) {
420                 error("invalid verity salt: %s", token.c_str());
421                 return -1;
422             }
423             break;
424         default:
425             break;
426         }
427     }
428 
429     if (i < VERITY_TABLE_ARGS) {
430         error("not enough arguments in verity table: %d; expected at least "
431             stringify(VERITY_TABLE_ARGS), i);
432         return -1;
433     }
434 
435     check(v->hash_start < f->data_size);
436 
437     if (v->metadata_start < v->hash_start) {
438         check(v->data_blocks == v->metadata_start / FEC_BLOCKSIZE);
439     } else {
440         check(v->data_blocks == v->hash_start / FEC_BLOCKSIZE);
441     }
442 
443     if (v->salt) {
444         delete[] v->salt;
445         v->salt = NULL;
446     }
447 
448     v->salt = salt.release();
449 
450     if (v->table) {
451         delete[] v->table;
452         v->table = NULL;
453     }
454 
455     v->table = table.release();
456 
457     if (!(f->flags & FEC_VERITY_DISABLE)) {
458         if (verify_tree(f, root) == -1) {
459             return -1;
460         }
461 
462         check(v->hash);
463 
464         uint8_t zero_block[FEC_BLOCKSIZE];
465         memset(zero_block, 0, FEC_BLOCKSIZE);
466 
467         if (verity_hash(f, zero_block, v->zero_hash) == -1) {
468             error("failed to hash");
469             return -1;
470         }
471     }
472 
473     return 0;
474 }
475 
476 /* rewrites verity metadata block using error corrected data in `f->verity' */
rewrite_metadata(fec_handle * f,uint64_t offset)477 static int rewrite_metadata(fec_handle *f, uint64_t offset)
478 {
479     check(f);
480     check(f->data_size > VERITY_METADATA_SIZE);
481     check(offset <= f->data_size - VERITY_METADATA_SIZE);
482 
483     std::unique_ptr<uint8_t[]> metadata(
484         new (std::nothrow) uint8_t[VERITY_METADATA_SIZE]);
485 
486     if (!metadata) {
487         errno = ENOMEM;
488         return -1;
489     }
490 
491     memset(metadata.get(), 0, VERITY_METADATA_SIZE);
492 
493     verity_info *v = &f->verity;
494     memcpy(metadata.get(), &v->header, sizeof(v->header));
495 
496     check(v->table);
497     size_t len = strlen(v->table);
498 
499     check(sizeof(v->header) + len <= VERITY_METADATA_SIZE);
500     memcpy(metadata.get() + sizeof(v->header), v->table, len);
501 
502     return raw_pwrite(f, metadata.get(), VERITY_METADATA_SIZE, offset);
503 }
504 
validate_header(const fec_handle * f,const verity_header * header,uint64_t offset)505 static int validate_header(const fec_handle *f, const verity_header *header,
506         uint64_t offset)
507 {
508     check(f);
509     check(header);
510 
511     if (header->magic != VERITY_MAGIC &&
512         header->magic != VERITY_MAGIC_DISABLE) {
513         return -1;
514     }
515 
516     if (header->version != VERITY_VERSION) {
517         error("unsupported verity version %u", header->version);
518         return -1;
519     }
520 
521     if (header->length < VERITY_MIN_TABLE_SIZE ||
522         header->length > VERITY_MAX_TABLE_SIZE) {
523         error("invalid verity table size: %u; expected ["
524             stringify(VERITY_MIN_TABLE_SIZE) ", "
525             stringify(VERITY_MAX_TABLE_SIZE) ")", header->length);
526         return -1;
527     }
528 
529     /* signature is skipped, because for our purposes it won't matter from
530        where the data originates; the caller of the library is responsible
531        for signature verification */
532 
533     if (offset > UINT64_MAX - header->length) {
534         error("invalid verity table length: %u", header->length);
535         return -1;
536     } else if (offset + header->length >= f->data_size) {
537         error("invalid verity table length: %u", header->length);
538         return -1;
539     }
540 
541     return 0;
542 }
543 
544 /* attempts to read verity metadata from `f->fd' position `offset'; if in r/w
545    mode, rewrites the metadata if it had errors */
verity_parse_header(fec_handle * f,uint64_t offset)546 int verity_parse_header(fec_handle *f, uint64_t offset)
547 {
548     check(f);
549     check(f->data_size > VERITY_METADATA_SIZE);
550 
551     if (offset > f->data_size - VERITY_METADATA_SIZE) {
552         debug("failed to read verity header: offset %" PRIu64 " is too far",
553             offset);
554         return -1;
555     }
556 
557     verity_info *v = &f->verity;
558     uint64_t errors = f->errors;
559 
560     if (!raw_pread(f, &v->header, sizeof(v->header), offset)) {
561         error("failed to read verity header: %s", strerror(errno));
562         return -1;
563     }
564 
565     /* use raw data to check for the alternative magic, because it will
566        be error corrected to VERITY_MAGIC otherwise */
567     if (v->header.magic == VERITY_MAGIC_DISABLE) {
568         /* this value is not used by us, but can be used by a caller to
569            decide whether dm-verity should be enabled */
570         v->disabled = true;
571     }
572 
573     if (fec_pread(f, &v->ecc_header, sizeof(v->ecc_header), offset) !=
574             sizeof(v->ecc_header)) {
575         warn("failed to read verity header: %s", strerror(errno));
576         return -1;
577     }
578 
579     if (validate_header(f, &v->header, offset)) {
580         /* raw verity header is invalid; this could be due to corruption, or
581            due to missing verity metadata */
582 
583         if (validate_header(f, &v->ecc_header, offset)) {
584             return -1; /* either way, we cannot recover */
585         }
586 
587         /* report mismatching fields */
588         if (!v->disabled && v->header.magic != v->ecc_header.magic) {
589             warn("corrected verity header magic");
590             v->header.magic = v->ecc_header.magic;
591         }
592 
593         if (v->header.version != v->ecc_header.version) {
594             warn("corrected verity header version");
595             v->header.version = v->ecc_header.version;
596         }
597 
598         if (v->header.length != v->ecc_header.length) {
599             warn("corrected verity header length");
600             v->header.length = v->ecc_header.length;
601         }
602 
603         if (memcmp(v->header.signature, v->ecc_header.signature,
604                 sizeof(v->header.signature))) {
605             warn("corrected verity header signature");
606             /* we have no way of knowing which signature is correct, if either
607                of them is */
608         }
609     }
610 
611     v->metadata_start = offset;
612 
613     if (parse_table(f, offset + sizeof(v->header), v->header.length,
614             false) == -1 &&
615         parse_table(f, offset + sizeof(v->header), v->header.length,
616             true)  == -1) {
617         return -1;
618     }
619 
620     /* if we corrected something while parsing metadata and we are in r/w
621        mode, rewrite the corrected metadata */
622     if (f->mode & O_RDWR && f->errors > errors &&
623             rewrite_metadata(f, offset) < 0) {
624         warn("failed to rewrite verity metadata: %s", strerror(errno));
625     }
626 
627     if (v->metadata_start < v->hash_start) {
628         f->data_size = v->metadata_start;
629     } else {
630         f->data_size = v->hash_start;
631     }
632 
633     return 0;
634 }
635 
fec_verity_set_status(struct fec_handle * f,bool enabled)636 int fec_verity_set_status(struct fec_handle *f, bool enabled)
637 {
638     check(f);
639 
640     if (!(f->mode & O_RDWR)) {
641         error("cannot update verity magic: read-only handle");
642         errno = EBADF;
643         return -1;
644     }
645 
646     verity_info *v = &f->verity;
647 
648     if (!v->metadata_start) {
649         error("cannot update verity magic: no metadata found");
650         errno = EINVAL;
651         return -1;
652     }
653 
654     if (v->disabled == !enabled) {
655         return 0; /* nothing to do */
656     }
657 
658     uint32_t magic = enabled ? VERITY_MAGIC : VERITY_MAGIC_DISABLE;
659 
660     if (!raw_pwrite(f, &magic, sizeof(magic), v->metadata_start)) {
661         error("failed to update verity magic to %08x: %s", magic,
662             strerror(errno));
663         return -1;
664     }
665 
666     warn("updated verity magic to %08x (%s)", magic,
667         enabled ? "enabled" : "disabled");
668     v->disabled = !enabled;
669 
670     return 0;
671 }
672