xref: /aosp_15_r20/bootable/recovery/install/spl_check.cpp (revision e7c364b630b241adcb6c7726a21055250b91fdac)
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