aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootloader.cpp134
-rw-r--r--install.cpp66
-rw-r--r--install.h17
-rw-r--r--recovery.cpp73
-rw-r--r--uncrypt/include/bootloader_message_writer.h35
-rw-r--r--uncrypt/uncrypt.cpp19
6 files changed, 140 insertions, 204 deletions
diff --git a/bootloader.cpp b/bootloader.cpp
deleted file mode 100644
index dad0bab3..00000000
--- a/bootloader.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
1/*
2 * Copyright (C) 2008 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 <errno.h>
18#include <fcntl.h>
19#include <inttypes.h>
20#include <stdio.h>
21#include <string.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <unistd.h>
25
26#include <fs_mgr.h>
27
28#include <android-base/logging.h>
29#include <android-base/unique_fd.h>
30
31#include "bootloader.h"
32#include "roots.h"
33
34static int get_bootloader_message_block(bootloader_message* out, const Volume* v);
35static int set_bootloader_message_block(const bootloader_message* in, const Volume* v);
36
37int get_bootloader_message(bootloader_message* out) {
38 Volume* v = volume_for_path("/misc");
39 if (v == nullptr) {
40 LOG(ERROR) << "Cannot load volume /misc!";
41 return -1;
42 }
43 if (strcmp(v->fs_type, "emmc") == 0) {
44 return get_bootloader_message_block(out, v);
45 }
46 LOG(ERROR) << "unknown misc partition fs_type \"" << v->fs_type << "\"";
47 return -1;
48}
49
50int set_bootloader_message(const bootloader_message* in) {
51 Volume* v = volume_for_path("/misc");
52 if (v == nullptr) {
53 LOG(ERROR) << "Cannot load volume /misc!";
54 return -1;
55 }
56 if (strcmp(v->fs_type, "emmc") == 0) {
57 return set_bootloader_message_block(in, v);
58 }
59 LOG(ERROR) << "unknown misc partition fs_type \"" << v->fs_type << "\"";
60 return -1;
61}
62
63// ------------------------------------
64// for misc partitions on block devices
65// ------------------------------------
66
67static void wait_for_device(const char* fn) {
68 int tries = 0;
69 int ret;
70 do {
71 ++tries;
72 struct stat buf;
73 ret = stat(fn, &buf);
74 if (ret == -1) {
75 printf("failed to stat \"%s\" try %d: %s\n", fn, tries, strerror(errno));
76 sleep(1);
77 }
78 } while (ret && tries < 10);
79
80 if (ret) {
81 printf("failed to stat \"%s\"\n", fn);
82 }
83}
84
85static int get_bootloader_message_block(bootloader_message* out,
86 const Volume* v) {
87 wait_for_device(v->blk_device);
88 FILE* f = fopen(v->blk_device, "rb");
89 if (f == nullptr) {
90 PLOG(ERROR) << "failed to open \"" << v->blk_device << "\"";
91 return -1;
92 }
93 bootloader_message temp;
94 int count = fread(&temp, sizeof(temp), 1, f);
95 if (count != 1) {
96 PLOG(ERROR) << "failed to read \"" << v->blk_device << "\"";
97 return -1;
98 }
99 if (fclose(f) != 0) {
100 PLOG(ERROR) << "failed to close \"" << v->blk_device << "\"";
101 return -1;
102 }
103 memcpy(out, &temp, sizeof(temp));
104 return 0;
105}
106
107static int set_bootloader_message_block(const bootloader_message* in,
108 const Volume* v) {
109 wait_for_device(v->blk_device);
110 android::base::unique_fd fd(open(v->blk_device, O_WRONLY | O_SYNC));
111 if (fd == -1) {
112 PLOG(ERROR) << "failed to open \"" << v->blk_device << "\"";
113 return -1;
114 }
115
116 size_t written = 0;
117 const uint8_t* start = reinterpret_cast<const uint8_t*>(in);
118 size_t total = sizeof(*in);
119 while (written < total) {
120 ssize_t wrote = TEMP_FAILURE_RETRY(write(fd, start + written, total - written));
121 if (wrote == -1) {
122 PLOG(ERROR) << "failed to write " << total << " bytes, " << written
123 << " bytes written";
124 return -1;
125 }
126 written += wrote;
127 }
128
129 if (fsync(fd) == -1) {
130 PLOG(ERROR) << "failed to fsync \"" << v->blk_device << "\"";
131 return -1;
132 }
133 return 0;
134}
diff --git a/install.cpp b/install.cpp
index c9871523..0f9088a7 100644
--- a/install.cpp
+++ b/install.cpp
@@ -71,22 +71,33 @@ static int parse_build_number(const std::string& str) {
71 return -1; 71 return -1;
72} 72}
73 73
74// Read the build.version.incremental of src/tgt from the metadata and log it to last_install. 74bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data) {
75static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::string>& log_buffer) {
76 ZipString metadata_path(METADATA_PATH); 75 ZipString metadata_path(METADATA_PATH);
77 ZipEntry meta_entry; 76 ZipEntry meta_entry;
77 if (meta_data == nullptr) {
78 LOG(ERROR) << "string* meta_data can't be nullptr";
79 return false;
80 }
78 if (FindEntry(zip, metadata_path, &meta_entry) != 0) { 81 if (FindEntry(zip, metadata_path, &meta_entry) != 0) {
79 LOG(ERROR) << "Failed to find " << METADATA_PATH << " in update package"; 82 LOG(ERROR) << "Failed to find " << METADATA_PATH << " in update package";
80 return; 83 return false;
81 } 84 }
82 85
83 std::string meta_data(meta_entry.uncompressed_length, '\0'); 86 meta_data->resize(meta_entry.uncompressed_length, '\0');
84 if (ExtractToMemory(zip, &meta_entry, reinterpret_cast<uint8_t*>(&meta_data[0]), 87 if (ExtractToMemory(zip, &meta_entry, reinterpret_cast<uint8_t*>(&(*meta_data)[0]),
85 meta_entry.uncompressed_length) != 0) { 88 meta_entry.uncompressed_length) != 0) {
86 LOG(ERROR) << "Failed to read metadata in update package"; 89 LOG(ERROR) << "Failed to read metadata in update package";
87 return; 90 return false;
88 } 91 }
92 return true;
93}
89 94
95// Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
96static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::string>& log_buffer) {
97 std::string meta_data;
98 if (!read_metadata_from_package(zip, &meta_data)) {
99 return;
100 }
90 // Examples of the pre-build and post-build strings in metadata: 101 // Examples of the pre-build and post-build strings in metadata:
91 // pre-build-incremental=2943039 102 // pre-build-incremental=2943039
92 // post-build-incremental=2951741 103 // post-build-incremental=2951741
@@ -301,33 +312,16 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
301 return INSTALL_CORRUPT; 312 return INSTALL_CORRUPT;
302 } 313 }
303 314
304 // Load keys.
305 std::vector<Certificate> loadedKeys;
306 if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
307 LOG(ERROR) << "Failed to load keys";
308 sysReleaseMap(&map);
309 return INSTALL_CORRUPT;
310 }
311 LOG(INFO) << loadedKeys.size() << " key(s) loaded from " << PUBLIC_KEYS_FILE;
312
313 // Verify package. 315 // Verify package.
314 ui->Print("Verifying update package...\n"); 316 if (!verify_package(map.addr, map.length)) {
315
316 auto t0 = std::chrono::system_clock::now();
317 int err = verify_file(map.addr, map.length, loadedKeys);
318 std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
319 ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
320 if (err != VERIFY_SUCCESS) {
321 LOG(ERROR) << "signature verification failed";
322 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure)); 317 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
323
324 sysReleaseMap(&map); 318 sysReleaseMap(&map);
325 return INSTALL_CORRUPT; 319 return INSTALL_CORRUPT;
326 } 320 }
327 321
328 // Try to open the package. 322 // Try to open the package.
329 ZipArchiveHandle zip; 323 ZipArchiveHandle zip;
330 err = OpenArchiveFromMemory(map.addr, map.length, path, &zip); 324 int err = OpenArchiveFromMemory(map.addr, map.length, path, &zip);
331 if (err != 0) { 325 if (err != 0) {
332 LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err); 326 LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err);
333 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure)); 327 log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
@@ -403,3 +397,25 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
403 397
404 return result; 398 return result;
405} 399}
400
401bool verify_package(const unsigned char* package_data, size_t package_size) {
402 std::vector<Certificate> loadedKeys;
403 if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
404 LOG(ERROR) << "Failed to load keys";
405 return false;
406 }
407 LOG(INFO) << loadedKeys.size() << " key(s) loaded from " << PUBLIC_KEYS_FILE;
408
409 // Verify package.
410 ui->Print("Verifying update package...\n");
411 auto t0 = std::chrono::system_clock::now();
412 int err = verify_file(const_cast<unsigned char*>(package_data), package_size, loadedKeys);
413 std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
414 ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
415 if (err != VERIFY_SUCCESS) {
416 LOG(ERROR) << "Signature verification failed";
417 LOG(ERROR) << "error: " << kZipVerificationFailure;
418 return false;
419 }
420 return true;
421}
diff --git a/install.h b/install.h
index 66764f54..7f66a51c 100644
--- a/install.h
+++ b/install.h
@@ -17,11 +17,10 @@
17#ifndef RECOVERY_INSTALL_H_ 17#ifndef RECOVERY_INSTALL_H_
18#define RECOVERY_INSTALL_H_ 18#define RECOVERY_INSTALL_H_
19 19
20#include "common.h" 20#include <string>
21#include <ziparchive/zip_archive.h>
21 22
22#ifdef __cplusplus 23#include "common.h"
23extern "C" {
24#endif
25 24
26enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SKIPPED, 25enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SKIPPED,
27 INSTALL_RETRY }; 26 INSTALL_RETRY };
@@ -31,8 +30,12 @@ enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SK
31int install_package(const char* root_path, bool* wipe_cache, const char* install_file, 30int install_package(const char* root_path, bool* wipe_cache, const char* install_file,
32 bool needs_mount, int retry_count); 31 bool needs_mount, int retry_count);
33 32
34#ifdef __cplusplus 33// Verify the package by ota keys. Return true if the package is verified successfully,
35} 34// otherwise return false.
36#endif 35bool verify_package(const unsigned char* package_data, size_t package_size);
36
37// Read meta data file of the package, write its content in the string pointed by meta_data.
38// Return true if succeed, otherwise return false.
39bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data);
37 40
38#endif // RECOVERY_INSTALL_H_ 41#endif // RECOVERY_INSTALL_H_
diff --git a/recovery.cpp b/recovery.cpp
index dc17c952..683d101f 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -86,6 +86,7 @@ static const struct option OPTIONS[] = {
86 { "reason", required_argument, NULL, 'r' }, 86 { "reason", required_argument, NULL, 'r' },
87 { "security", no_argument, NULL, 'e'}, 87 { "security", no_argument, NULL, 'e'},
88 { "wipe_ab", no_argument, NULL, 0 }, 88 { "wipe_ab", no_argument, NULL, 0 },
89 { "wipe_package_size", required_argument, NULL, 0 },
89 { NULL, 0, NULL, 0 }, 90 { NULL, 0, NULL, 0 },
90}; 91};
91 92
@@ -902,12 +903,76 @@ static bool secure_wipe_partition(const std::string& partition) {
902 return true; 903 return true;
903} 904}
904 905
906// Check if the wipe package matches expectation:
907// 1. verify the package.
908// 2. check metadata (ota-type, pre-device and serial number if having one).
909static bool check_wipe_package(size_t wipe_package_size) {
910 if (wipe_package_size == 0) {
911 LOG(ERROR) << "wipe_package_size is zero";
912 return false;
913 }
914 std::string wipe_package;
915 std::string err_str;
916 if (!read_wipe_package(&wipe_package, wipe_package_size, &err_str)) {
917 PLOG(ERROR) << "Failed to read wipe package";
918 return false;
919 }
920 if (!verify_package(reinterpret_cast<const unsigned char*>(wipe_package.data()),
921 wipe_package.size())) {
922 LOG(ERROR) << "Failed to verify package";
923 return false;
924 }
925
926 // Extract metadata
927 ZipArchiveHandle zip;
928 int err = OpenArchiveFromMemory(reinterpret_cast<void*>(&wipe_package[0]),
929 wipe_package.size(), "wipe_package", &zip);
930 if (err != 0) {
931 LOG(ERROR) << "Can't open wipe package : " << ErrorCodeString(err);
932 return false;
933 }
934 std::string metadata;
935 if (!read_metadata_from_package(&zip, &metadata)) {
936 CloseArchive(zip);
937 return false;
938 }
939 CloseArchive(zip);
940
941 // Check metadata
942 std::vector<std::string> lines = android::base::Split(metadata, "\n");
943 bool ota_type_matched = false;
944 bool device_type_matched = false;
945 bool has_serial_number = false;
946 bool serial_number_matched = false;
947 for (const auto& line : lines) {
948 if (line == "ota-type=BRICK") {
949 ota_type_matched = true;
950 } else if (android::base::StartsWith(line, "pre-device=")) {
951 std::string device_type = line.substr(strlen("pre-device="));
952 char real_device_type[PROPERTY_VALUE_MAX];
953 property_get("ro.build.product", real_device_type, "");
954 device_type_matched = (device_type == real_device_type);
955 } else if (android::base::StartsWith(line, "serialno=")) {
956 std::string serial_no = line.substr(strlen("serialno="));
957 char real_serial_no[PROPERTY_VALUE_MAX];
958 property_get("ro.serialno", real_serial_no, "");
959 has_serial_number = true;
960 serial_number_matched = (serial_no == real_serial_no);
961 }
962 }
963 return ota_type_matched && device_type_matched && (!has_serial_number || serial_number_matched);
964}
965
905// Wipe the current A/B device, with a secure wipe of all the partitions in 966// Wipe the current A/B device, with a secure wipe of all the partitions in
906// RECOVERY_WIPE. 967// RECOVERY_WIPE.
907static bool wipe_ab_device() { 968static bool wipe_ab_device(size_t wipe_package_size) {
908 ui->SetBackground(RecoveryUI::ERASING); 969 ui->SetBackground(RecoveryUI::ERASING);
909 ui->SetProgressType(RecoveryUI::INDETERMINATE); 970 ui->SetProgressType(RecoveryUI::INDETERMINATE);
910 971
972 if (!check_wipe_package(wipe_package_size)) {
973 LOG(ERROR) << "Failed to verify wipe package";
974 return false;
975 }
911 std::string partition_list; 976 std::string partition_list;
912 if (!android::base::ReadFileToString(RECOVERY_WIPE, &partition_list)) { 977 if (!android::base::ReadFileToString(RECOVERY_WIPE, &partition_list)) {
913 LOG(ERROR) << "failed to read \"" << RECOVERY_WIPE << "\""; 978 LOG(ERROR) << "failed to read \"" << RECOVERY_WIPE << "\"";
@@ -1426,6 +1491,7 @@ int main(int argc, char **argv) {
1426 bool should_wipe_data = false; 1491 bool should_wipe_data = false;
1427 bool should_wipe_cache = false; 1492 bool should_wipe_cache = false;
1428 bool should_wipe_ab = false; 1493 bool should_wipe_ab = false;
1494 size_t wipe_package_size = 0;
1429 bool show_text = false; 1495 bool show_text = false;
1430 bool sideload = false; 1496 bool sideload = false;
1431 bool sideload_auto_reboot = false; 1497 bool sideload_auto_reboot = false;
@@ -1462,6 +1528,9 @@ int main(int argc, char **argv) {
1462 if (strcmp(OPTIONS[option_index].name, "wipe_ab") == 0) { 1528 if (strcmp(OPTIONS[option_index].name, "wipe_ab") == 0) {
1463 should_wipe_ab = true; 1529 should_wipe_ab = true;
1464 break; 1530 break;
1531 } else if (strcmp(OPTIONS[option_index].name, "wipe_package_size") == 0) {
1532 android::base::ParseUint(optarg, &wipe_package_size);
1533 break;
1465 } 1534 }
1466 break; 1535 break;
1467 } 1536 }
@@ -1607,7 +1676,7 @@ int main(int argc, char **argv) {
1607 status = INSTALL_ERROR; 1676 status = INSTALL_ERROR;
1608 } 1677 }
1609 } else if (should_wipe_ab) { 1678 } else if (should_wipe_ab) {
1610 if (!wipe_ab_device()) { 1679 if (!wipe_ab_device(wipe_package_size)) {
1611 status = INSTALL_ERROR; 1680 status = INSTALL_ERROR;
1612 } 1681 }
1613 } else if (sideload) { 1682 } else if (sideload) {
diff --git a/uncrypt/include/bootloader_message_writer.h b/uncrypt/include/bootloader_message_writer.h
deleted file mode 100644
index e0ca3f44..00000000
--- a/uncrypt/include/bootloader_message_writer.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2016 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#ifndef BOOTLOADER_MESSAGE_WRITER_H
18#define BOOTLOADER_MESSAGE_WRITER_H
19
20#ifdef __cplusplus
21#include <string>
22#include <vector>
23
24bool clear_bootloader_message(std::string* err);
25
26bool write_bootloader_message(const std::vector<std::string>& options, std::string* err);
27
28#else
29#include <stdbool.h>
30
31// C Interface.
32bool write_bootloader_message(const char* options);
33#endif
34
35#endif // BOOTLOADER_MESSAGE_WRITER_H
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp
index 8b4d8ef8..a5d692bb 100644
--- a/uncrypt/uncrypt.cpp
+++ b/uncrypt/uncrypt.cpp
@@ -528,14 +528,31 @@ static bool setup_bcb(const int socket) {
528 return false; 528 return false;
529 } 529 }
530 LOG(INFO) << " received command: [" << content << "] (" << content.size() << ")"; 530 LOG(INFO) << " received command: [" << content << "] (" << content.size() << ")";
531 std::vector<std::string> options = android::base::Split(content, "\n");
532 std::string wipe_package;
533 for (auto& option : options) {
534 if (android::base::StartsWith(option, "--wipe_package=")) {
535 std::string path = option.substr(strlen("--wipe_package="));
536 if (!android::base::ReadFileToString(path, &wipe_package)) {
537 PLOG(ERROR) << "failed to read " << path;
538 return false;
539 }
540 option = android::base::StringPrintf("--wipe_package_size=%zu", wipe_package.size());
541 }
542 }
531 543
532 // c8. setup the bcb command 544 // c8. setup the bcb command
533 std::string err; 545 std::string err;
534 if (!write_bootloader_message({content}, &err)) { 546 if (!write_bootloader_message(options, &err)) {
535 LOG(ERROR) << "failed to set bootloader message: " << err; 547 LOG(ERROR) << "failed to set bootloader message: " << err;
536 write_status_to_socket(-1, socket); 548 write_status_to_socket(-1, socket);
537 return false; 549 return false;
538 } 550 }
551 if (!wipe_package.empty() && !write_wipe_package(wipe_package, &err)) {
552 PLOG(ERROR) << "failed to set wipe package: " << err;
553 write_status_to_socket(-1, socket);
554 return false;
555 }
539 // c10. send "100" status 556 // c10. send "100" status
540 write_status_to_socket(100, socket); 557 write_status_to_socket(100, socket);
541 return true; 558 return true;