1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include "install/spl_check.h"
18*e7c364b6SAndroid Build Coastguard Worker
ViolatesSPLDowngrade(const build::tools::releasetools::OtaMetadata & metadata,std::string_view current_spl)19*e7c364b6SAndroid Build Coastguard Worker bool ViolatesSPLDowngrade(const build::tools::releasetools::OtaMetadata& metadata,
20*e7c364b6SAndroid Build Coastguard Worker std::string_view current_spl) {
21*e7c364b6SAndroid Build Coastguard Worker const auto& post_spl = metadata.postcondition().security_patch_level();
22*e7c364b6SAndroid Build Coastguard Worker if (current_spl.empty()) {
23*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to get device's current security patch level. Target SPL is "
24*e7c364b6SAndroid Build Coastguard Worker << post_spl << " permitting OTA install";
25*e7c364b6SAndroid Build Coastguard Worker return false;
26*e7c364b6SAndroid Build Coastguard Worker }
27*e7c364b6SAndroid Build Coastguard Worker // SPL(security patch level) is expected to be in format yyyy-mm-dd, e.g. 2018-05-29. Given this
28*e7c364b6SAndroid Build Coastguard Worker // specific format, comparing two SPL can be done by just regular string comparison. If the format
29*e7c364b6SAndroid Build Coastguard Worker // must lay out year/month/date in the exact order, and must properly prepend dates with 0(for
30*e7c364b6SAndroid Build Coastguard Worker // example, 05 for May). Otherwise this comparison doesn't work. We don't expect SPL date formats
31*e7c364b6SAndroid Build Coastguard Worker // to change, leave this as is.
32*e7c364b6SAndroid Build Coastguard Worker if (post_spl < current_spl) {
33*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Current SPL: " << current_spl << " Target SPL: " << post_spl
34*e7c364b6SAndroid Build Coastguard Worker << " this is considered a downgrade";
35*e7c364b6SAndroid Build Coastguard Worker if (metadata.spl_downgrade() || metadata.downgrade()) {
36*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING)
37*e7c364b6SAndroid Build Coastguard Worker << "SPL downgrade detected, but OTA package explicitly permitts this(OtaMetadata has "
38*e7c364b6SAndroid Build Coastguard Worker "spl_downgrade / downgrade bit set).Permitting update anyway.Installing a SPL "
39*e7c364b6SAndroid Build Coastguard Worker "downgrade OTA can cause /data fail to decrypt and device fails to boot.";
40*e7c364b6SAndroid Build Coastguard Worker return false;
41*e7c364b6SAndroid Build Coastguard Worker }
42*e7c364b6SAndroid Build Coastguard Worker return true;
43*e7c364b6SAndroid Build Coastguard Worker } else {
44*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "old spl: " << current_spl << " new spl: " << post_spl << " CHECK passes";
45*e7c364b6SAndroid Build Coastguard Worker }
46*e7c364b6SAndroid Build Coastguard Worker return false;
47*e7c364b6SAndroid Build Coastguard Worker }
48*e7c364b6SAndroid Build Coastguard Worker
ViolatesSPLDowngrade(ZipArchiveHandle zip,std::string_view current_spl)49*e7c364b6SAndroid Build Coastguard Worker bool ViolatesSPLDowngrade(ZipArchiveHandle zip, std::string_view current_spl) {
50*e7c364b6SAndroid Build Coastguard Worker static constexpr auto&& OTA_OTA_METADATA = "META-INF/com/android/metadata.pb";
51*e7c364b6SAndroid Build Coastguard Worker ZipEntry64 metadata_entry;
52*e7c364b6SAndroid Build Coastguard Worker if (FindEntry(zip, OTA_OTA_METADATA, &metadata_entry) != 0) {
53*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to find " << OTA_OTA_METADATA
54*e7c364b6SAndroid Build Coastguard Worker << " treating this as non-spl-downgrade, permit OTA install. If device bricks "
55*e7c364b6SAndroid Build Coastguard Worker "after installing, check kernel log to see if /data failed to decrypt";
56*e7c364b6SAndroid Build Coastguard Worker return false;
57*e7c364b6SAndroid Build Coastguard Worker }
58*e7c364b6SAndroid Build Coastguard Worker const auto metadata_entry_length = metadata_entry.uncompressed_length;
59*e7c364b6SAndroid Build Coastguard Worker if (metadata_entry_length > std::numeric_limits<size_t>::max()) {
60*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to extract " << OTA_OTA_METADATA
61*e7c364b6SAndroid Build Coastguard Worker << " because's uncompressed size exceeds size of address space. "
62*e7c364b6SAndroid Build Coastguard Worker << metadata_entry_length;
63*e7c364b6SAndroid Build Coastguard Worker return false;
64*e7c364b6SAndroid Build Coastguard Worker }
65*e7c364b6SAndroid Build Coastguard Worker std::vector<uint8_t> ota_metadata(metadata_entry_length);
66*e7c364b6SAndroid Build Coastguard Worker int32_t err = ExtractToMemory(zip, &metadata_entry, ota_metadata.data(), metadata_entry_length);
67*e7c364b6SAndroid Build Coastguard Worker if (err != 0) {
68*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to extract " << OTA_OTA_METADATA << ": " << ErrorCodeString(err);
69*e7c364b6SAndroid Build Coastguard Worker return false;
70*e7c364b6SAndroid Build Coastguard Worker }
71*e7c364b6SAndroid Build Coastguard Worker using build::tools::releasetools::OtaMetadata;
72*e7c364b6SAndroid Build Coastguard Worker OtaMetadata metadata;
73*e7c364b6SAndroid Build Coastguard Worker if (!metadata.ParseFromArray(ota_metadata.data(), ota_metadata.size())) {
74*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse ota_medata";
75*e7c364b6SAndroid Build Coastguard Worker return false;
76*e7c364b6SAndroid Build Coastguard Worker }
77*e7c364b6SAndroid Build Coastguard Worker return ViolatesSPLDowngrade(metadata, current_spl);
78*e7c364b6SAndroid Build Coastguard Worker }
79