1*e1997b9aSAndroid Build Coastguard Worker /*
2*e1997b9aSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*e1997b9aSAndroid Build Coastguard Worker *
4*e1997b9aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e1997b9aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e1997b9aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e1997b9aSAndroid Build Coastguard Worker *
8*e1997b9aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e1997b9aSAndroid Build Coastguard Worker *
10*e1997b9aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e1997b9aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e1997b9aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1997b9aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e1997b9aSAndroid Build Coastguard Worker * limitations under the License.
15*e1997b9aSAndroid Build Coastguard Worker */
16*e1997b9aSAndroid Build Coastguard Worker
17*e1997b9aSAndroid Build Coastguard Worker #include <fcntl.h>
18*e1997b9aSAndroid Build Coastguard Worker #include <filesystem>
19*e1997b9aSAndroid Build Coastguard Worker #include <fstream>
20*e1997b9aSAndroid Build Coastguard Worker #include <iomanip>
21*e1997b9aSAndroid Build Coastguard Worker #include <iostream>
22*e1997b9aSAndroid Build Coastguard Worker #include <iterator>
23*e1997b9aSAndroid Build Coastguard Worker #include <sys/stat.h>
24*e1997b9aSAndroid Build Coastguard Worker #include <sys/types.h>
25*e1997b9aSAndroid Build Coastguard Worker #include <unistd.h>
26*e1997b9aSAndroid Build Coastguard Worker
27*e1997b9aSAndroid Build Coastguard Worker #include <android-base/file.h>
28*e1997b9aSAndroid Build Coastguard Worker #include <android-base/logging.h>
29*e1997b9aSAndroid Build Coastguard Worker #include <android-base/properties.h>
30*e1997b9aSAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
31*e1997b9aSAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
32*e1997b9aSAndroid Build Coastguard Worker #include <odrefresh/odrefresh.h>
33*e1997b9aSAndroid Build Coastguard Worker
34*e1997b9aSAndroid Build Coastguard Worker #include "CertUtils.h"
35*e1997b9aSAndroid Build Coastguard Worker #include "KeystoreKey.h"
36*e1997b9aSAndroid Build Coastguard Worker #include "StatsReporter.h"
37*e1997b9aSAndroid Build Coastguard Worker #include "VerityUtils.h"
38*e1997b9aSAndroid Build Coastguard Worker #include "statslog_odsign.h"
39*e1997b9aSAndroid Build Coastguard Worker
40*e1997b9aSAndroid Build Coastguard Worker #include "odsign_info.pb.h"
41*e1997b9aSAndroid Build Coastguard Worker
42*e1997b9aSAndroid Build Coastguard Worker using android::base::ErrnoError;
43*e1997b9aSAndroid Build Coastguard Worker using android::base::Error;
44*e1997b9aSAndroid Build Coastguard Worker using android::base::Result;
45*e1997b9aSAndroid Build Coastguard Worker using android::base::SetProperty;
46*e1997b9aSAndroid Build Coastguard Worker
47*e1997b9aSAndroid Build Coastguard Worker using OdsignInfo = ::odsign::proto::OdsignInfo;
48*e1997b9aSAndroid Build Coastguard Worker
49*e1997b9aSAndroid Build Coastguard Worker // Keystore boot level that the odsign key uses
50*e1997b9aSAndroid Build Coastguard Worker const int kKeyBootLevel = 30;
51*e1997b9aSAndroid Build Coastguard Worker const std::string kPublicKeySignature = "/data/misc/odsign/publickey.signature";
52*e1997b9aSAndroid Build Coastguard Worker const android::String16 kKeyAlias{"ondevice-signing"};
53*e1997b9aSAndroid Build Coastguard Worker constexpr int kKeyNspace = 101; // odsign_key
54*e1997b9aSAndroid Build Coastguard Worker
55*e1997b9aSAndroid Build Coastguard Worker const std::string kSigningKeyCert = "/data/misc/odsign/key.cert";
56*e1997b9aSAndroid Build Coastguard Worker const std::string kOdsignInfo = "/data/misc/odsign/odsign.info";
57*e1997b9aSAndroid Build Coastguard Worker const std::string kOdsignInfoSignature = "/data/misc/odsign/odsign.info.signature";
58*e1997b9aSAndroid Build Coastguard Worker
59*e1997b9aSAndroid Build Coastguard Worker const std::string kArtArtifactsDir = "/data/misc/apexdata/com.android.art/dalvik-cache";
60*e1997b9aSAndroid Build Coastguard Worker
61*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdrefreshPath = "/apex/com.android.art/bin/odrefresh";
62*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kCompOsVerifyPath = "/apex/com.android.compos/bin/compos_verify";
63*e1997b9aSAndroid Build Coastguard Worker
64*e1997b9aSAndroid Build Coastguard Worker constexpr bool kForceCompilation = false;
65*e1997b9aSAndroid Build Coastguard Worker constexpr bool kUseCompOs = true;
66*e1997b9aSAndroid Build Coastguard Worker
67*e1997b9aSAndroid Build Coastguard Worker const std::string kCompOsPendingArtifactsDir = "/data/misc/apexdata/com.android.art/compos-pending";
68*e1997b9aSAndroid Build Coastguard Worker const std::string kCompOsInfo = kArtArtifactsDir + "/compos.info";
69*e1997b9aSAndroid Build Coastguard Worker const std::string kCompOsInfoSignature = kCompOsInfo + ".signature";
70*e1997b9aSAndroid Build Coastguard Worker
71*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kCompOsPendingInfoPath =
72*e1997b9aSAndroid Build Coastguard Worker "/data/misc/apexdata/com.android.art/compos-pending/compos.info";
73*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kCompOsPendingInfoSignaturePath =
74*e1997b9aSAndroid Build Coastguard Worker "/data/misc/apexdata/com.android.art/compos-pending/compos.info.signature";
75*e1997b9aSAndroid Build Coastguard Worker
76*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdsignVerificationDoneProp = "odsign.verification.done";
77*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdsignKeyDoneProp = "odsign.key.done";
78*e1997b9aSAndroid Build Coastguard Worker
79*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdsignVerificationStatusProp = "odsign.verification.success";
80*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdsignVerificationStatusValid = "1";
81*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kOdsignVerificationStatusError = "0";
82*e1997b9aSAndroid Build Coastguard Worker
83*e1997b9aSAndroid Build Coastguard Worker constexpr const char* kStopServiceProp = "ctl.stop";
84*e1997b9aSAndroid Build Coastguard Worker
85*e1997b9aSAndroid Build Coastguard Worker enum class CompOsInstance { kCurrent, kPending };
86*e1997b9aSAndroid Build Coastguard Worker
87*e1997b9aSAndroid Build Coastguard Worker namespace {
88*e1997b9aSAndroid Build Coastguard Worker
rename(const std::string & from,const std::string & to)89*e1997b9aSAndroid Build Coastguard Worker bool rename(const std::string& from, const std::string& to) {
90*e1997b9aSAndroid Build Coastguard Worker std::error_code ec;
91*e1997b9aSAndroid Build Coastguard Worker std::filesystem::rename(from, to, ec);
92*e1997b9aSAndroid Build Coastguard Worker if (ec) {
93*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Can't rename " << from << " to " << to << ": " << ec.message();
94*e1997b9aSAndroid Build Coastguard Worker return false;
95*e1997b9aSAndroid Build Coastguard Worker }
96*e1997b9aSAndroid Build Coastguard Worker return true;
97*e1997b9aSAndroid Build Coastguard Worker }
98*e1997b9aSAndroid Build Coastguard Worker
removeDirectory(const std::string & directory)99*e1997b9aSAndroid Build Coastguard Worker int removeDirectory(const std::string& directory) {
100*e1997b9aSAndroid Build Coastguard Worker std::error_code ec;
101*e1997b9aSAndroid Build Coastguard Worker auto num_removed = std::filesystem::remove_all(directory, ec);
102*e1997b9aSAndroid Build Coastguard Worker if (ec) {
103*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Can't remove " << directory << ": " << ec.message();
104*e1997b9aSAndroid Build Coastguard Worker return 0;
105*e1997b9aSAndroid Build Coastguard Worker } else {
106*e1997b9aSAndroid Build Coastguard Worker if (num_removed > 0) {
107*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Removed " << num_removed << " entries from " << directory;
108*e1997b9aSAndroid Build Coastguard Worker }
109*e1997b9aSAndroid Build Coastguard Worker return num_removed;
110*e1997b9aSAndroid Build Coastguard Worker }
111*e1997b9aSAndroid Build Coastguard Worker }
112*e1997b9aSAndroid Build Coastguard Worker
directoryHasContent(const std::string & directory)113*e1997b9aSAndroid Build Coastguard Worker bool directoryHasContent(const std::string& directory) {
114*e1997b9aSAndroid Build Coastguard Worker std::error_code ec;
115*e1997b9aSAndroid Build Coastguard Worker return std::filesystem::is_directory(directory, ec) &&
116*e1997b9aSAndroid Build Coastguard Worker !std::filesystem::is_empty(directory, ec);
117*e1997b9aSAndroid Build Coastguard Worker }
118*e1997b9aSAndroid Build Coastguard Worker
compileArtifacts(bool force)119*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode compileArtifacts(bool force) {
120*e1997b9aSAndroid Build Coastguard Worker const char* const argv[] = {kOdrefreshPath, force ? "--force-compile" : "--compile"};
121*e1997b9aSAndroid Build Coastguard Worker const int exit_code =
122*e1997b9aSAndroid Build Coastguard Worker logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
123*e1997b9aSAndroid Build Coastguard Worker return static_cast<art::odrefresh::ExitCode>(exit_code);
124*e1997b9aSAndroid Build Coastguard Worker }
125*e1997b9aSAndroid Build Coastguard Worker
checkArtifacts()126*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode checkArtifacts() {
127*e1997b9aSAndroid Build Coastguard Worker const char* const argv[] = {kOdrefreshPath, "--check"};
128*e1997b9aSAndroid Build Coastguard Worker const int exit_code =
129*e1997b9aSAndroid Build Coastguard Worker logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
130*e1997b9aSAndroid Build Coastguard Worker return static_cast<art::odrefresh::ExitCode>(exit_code);
131*e1997b9aSAndroid Build Coastguard Worker }
132*e1997b9aSAndroid Build Coastguard Worker
toHex(const std::vector<uint8_t> & digest)133*e1997b9aSAndroid Build Coastguard Worker std::string toHex(const std::vector<uint8_t>& digest) {
134*e1997b9aSAndroid Build Coastguard Worker std::stringstream ss;
135*e1997b9aSAndroid Build Coastguard Worker for (auto it = digest.begin(); it != digest.end(); ++it) {
136*e1997b9aSAndroid Build Coastguard Worker ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(*it);
137*e1997b9aSAndroid Build Coastguard Worker }
138*e1997b9aSAndroid Build Coastguard Worker return ss.str();
139*e1997b9aSAndroid Build Coastguard Worker }
140*e1997b9aSAndroid Build Coastguard Worker
compOsPresent()141*e1997b9aSAndroid Build Coastguard Worker bool compOsPresent() {
142*e1997b9aSAndroid Build Coastguard Worker // We must have the CompOS APEX
143*e1997b9aSAndroid Build Coastguard Worker return access(kCompOsVerifyPath, X_OK) == 0;
144*e1997b9aSAndroid Build Coastguard Worker }
145*e1997b9aSAndroid Build Coastguard Worker
verifyExistingRootCert(const SigningKey & key)146*e1997b9aSAndroid Build Coastguard Worker Result<void> verifyExistingRootCert(const SigningKey& key) {
147*e1997b9aSAndroid Build Coastguard Worker if (access(kSigningKeyCert.c_str(), F_OK) < 0) {
148*e1997b9aSAndroid Build Coastguard Worker return ErrnoError() << "Key certificate not found: " << kSigningKeyCert;
149*e1997b9aSAndroid Build Coastguard Worker }
150*e1997b9aSAndroid Build Coastguard Worker auto trustedPublicKey = key.getPublicKey();
151*e1997b9aSAndroid Build Coastguard Worker if (!trustedPublicKey.ok()) {
152*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to retrieve signing public key: " << trustedPublicKey.error();
153*e1997b9aSAndroid Build Coastguard Worker }
154*e1997b9aSAndroid Build Coastguard Worker
155*e1997b9aSAndroid Build Coastguard Worker auto publicKeyFromExistingCert = extractPublicKeyFromX509(kSigningKeyCert);
156*e1997b9aSAndroid Build Coastguard Worker if (!publicKeyFromExistingCert.ok()) {
157*e1997b9aSAndroid Build Coastguard Worker return publicKeyFromExistingCert.error();
158*e1997b9aSAndroid Build Coastguard Worker }
159*e1997b9aSAndroid Build Coastguard Worker if (publicKeyFromExistingCert.value() != trustedPublicKey.value()) {
160*e1997b9aSAndroid Build Coastguard Worker return Error() << "Public key of existing certificate at " << kSigningKeyCert
161*e1997b9aSAndroid Build Coastguard Worker << " does not match signing public key.";
162*e1997b9aSAndroid Build Coastguard Worker }
163*e1997b9aSAndroid Build Coastguard Worker
164*e1997b9aSAndroid Build Coastguard Worker // At this point, we know the cert is for our key; it's unimportant whether it's
165*e1997b9aSAndroid Build Coastguard Worker // actually self-signed.
166*e1997b9aSAndroid Build Coastguard Worker return {};
167*e1997b9aSAndroid Build Coastguard Worker }
168*e1997b9aSAndroid Build Coastguard Worker
createX509RootCert(const SigningKey & key,const std::string & outPath)169*e1997b9aSAndroid Build Coastguard Worker Result<void> createX509RootCert(const SigningKey& key, const std::string& outPath) {
170*e1997b9aSAndroid Build Coastguard Worker auto publicKey = key.getPublicKey();
171*e1997b9aSAndroid Build Coastguard Worker
172*e1997b9aSAndroid Build Coastguard Worker if (!publicKey.ok()) {
173*e1997b9aSAndroid Build Coastguard Worker return publicKey.error();
174*e1997b9aSAndroid Build Coastguard Worker }
175*e1997b9aSAndroid Build Coastguard Worker
176*e1997b9aSAndroid Build Coastguard Worker auto keySignFunction = [&](const std::string& to_be_signed) { return key.sign(to_be_signed); };
177*e1997b9aSAndroid Build Coastguard Worker return createSelfSignedCertificate(*publicKey, keySignFunction, outPath);
178*e1997b9aSAndroid Build Coastguard Worker }
179*e1997b9aSAndroid Build Coastguard Worker
computeDigests(const std::string & path)180*e1997b9aSAndroid Build Coastguard Worker Result<std::map<std::string, std::string>> computeDigests(const std::string& path) {
181*e1997b9aSAndroid Build Coastguard Worker std::error_code ec;
182*e1997b9aSAndroid Build Coastguard Worker std::map<std::string, std::string> digests;
183*e1997b9aSAndroid Build Coastguard Worker
184*e1997b9aSAndroid Build Coastguard Worker auto it = std::filesystem::recursive_directory_iterator(path, ec);
185*e1997b9aSAndroid Build Coastguard Worker auto end = std::filesystem::recursive_directory_iterator();
186*e1997b9aSAndroid Build Coastguard Worker
187*e1997b9aSAndroid Build Coastguard Worker while (!ec && it != end) {
188*e1997b9aSAndroid Build Coastguard Worker if (it->is_regular_file()) {
189*e1997b9aSAndroid Build Coastguard Worker auto digest = createDigest(it->path());
190*e1997b9aSAndroid Build Coastguard Worker if (!digest.ok()) {
191*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to compute digest for " << it->path() << ": "
192*e1997b9aSAndroid Build Coastguard Worker << digest.error();
193*e1997b9aSAndroid Build Coastguard Worker }
194*e1997b9aSAndroid Build Coastguard Worker digests[it->path()] = toHex(*digest);
195*e1997b9aSAndroid Build Coastguard Worker }
196*e1997b9aSAndroid Build Coastguard Worker ++it;
197*e1997b9aSAndroid Build Coastguard Worker }
198*e1997b9aSAndroid Build Coastguard Worker if (ec) {
199*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to iterate " << path << ": " << ec;
200*e1997b9aSAndroid Build Coastguard Worker }
201*e1997b9aSAndroid Build Coastguard Worker
202*e1997b9aSAndroid Build Coastguard Worker return digests;
203*e1997b9aSAndroid Build Coastguard Worker }
204*e1997b9aSAndroid Build Coastguard Worker
verifyDigests(const std::map<std::string,std::string> & digests,const std::map<std::string,std::string> & trusted_digests)205*e1997b9aSAndroid Build Coastguard Worker Result<void> verifyDigests(const std::map<std::string, std::string>& digests,
206*e1997b9aSAndroid Build Coastguard Worker const std::map<std::string, std::string>& trusted_digests) {
207*e1997b9aSAndroid Build Coastguard Worker for (const auto& path_digest : digests) {
208*e1997b9aSAndroid Build Coastguard Worker auto path = path_digest.first;
209*e1997b9aSAndroid Build Coastguard Worker auto digest = path_digest.second;
210*e1997b9aSAndroid Build Coastguard Worker if (trusted_digests.count(path) == 0) {
211*e1997b9aSAndroid Build Coastguard Worker return Error() << "Couldn't find digest for " << path;
212*e1997b9aSAndroid Build Coastguard Worker }
213*e1997b9aSAndroid Build Coastguard Worker if (trusted_digests.at(path) != digest) {
214*e1997b9aSAndroid Build Coastguard Worker return Error() << "Digest mismatch for " << path;
215*e1997b9aSAndroid Build Coastguard Worker }
216*e1997b9aSAndroid Build Coastguard Worker }
217*e1997b9aSAndroid Build Coastguard Worker
218*e1997b9aSAndroid Build Coastguard Worker // All digests matched!
219*e1997b9aSAndroid Build Coastguard Worker if (digests.size() > 0) {
220*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "All root hashes match.";
221*e1997b9aSAndroid Build Coastguard Worker }
222*e1997b9aSAndroid Build Coastguard Worker return {};
223*e1997b9aSAndroid Build Coastguard Worker }
224*e1997b9aSAndroid Build Coastguard Worker
verifyIntegrityFsVerity(const std::map<std::string,std::string> & trusted_digests)225*e1997b9aSAndroid Build Coastguard Worker Result<void> verifyIntegrityFsVerity(const std::map<std::string, std::string>& trusted_digests) {
226*e1997b9aSAndroid Build Coastguard Worker // Just verify that the files are in verity, and get their digests
227*e1997b9aSAndroid Build Coastguard Worker auto result = verifyAllFilesInVerity(kArtArtifactsDir);
228*e1997b9aSAndroid Build Coastguard Worker if (!result.ok()) {
229*e1997b9aSAndroid Build Coastguard Worker return result.error();
230*e1997b9aSAndroid Build Coastguard Worker }
231*e1997b9aSAndroid Build Coastguard Worker
232*e1997b9aSAndroid Build Coastguard Worker return verifyDigests(*result, trusted_digests);
233*e1997b9aSAndroid Build Coastguard Worker }
234*e1997b9aSAndroid Build Coastguard Worker
verifyIntegrityNoFsVerity(const std::map<std::string,std::string> & trusted_digests)235*e1997b9aSAndroid Build Coastguard Worker Result<void> verifyIntegrityNoFsVerity(const std::map<std::string, std::string>& trusted_digests) {
236*e1997b9aSAndroid Build Coastguard Worker // On these devices, just compute the digests, and verify they match the ones we trust
237*e1997b9aSAndroid Build Coastguard Worker auto result = computeDigests(kArtArtifactsDir);
238*e1997b9aSAndroid Build Coastguard Worker if (!result.ok()) {
239*e1997b9aSAndroid Build Coastguard Worker return result.error();
240*e1997b9aSAndroid Build Coastguard Worker }
241*e1997b9aSAndroid Build Coastguard Worker
242*e1997b9aSAndroid Build Coastguard Worker return verifyDigests(*result, trusted_digests);
243*e1997b9aSAndroid Build Coastguard Worker }
244*e1997b9aSAndroid Build Coastguard Worker
getAndVerifyOdsignInfo(const SigningKey & key)245*e1997b9aSAndroid Build Coastguard Worker Result<OdsignInfo> getAndVerifyOdsignInfo(const SigningKey& key) {
246*e1997b9aSAndroid Build Coastguard Worker std::string persistedSignature;
247*e1997b9aSAndroid Build Coastguard Worker OdsignInfo odsignInfo;
248*e1997b9aSAndroid Build Coastguard Worker
249*e1997b9aSAndroid Build Coastguard Worker if (!android::base::ReadFileToString(kOdsignInfoSignature, &persistedSignature)) {
250*e1997b9aSAndroid Build Coastguard Worker return ErrnoError() << "Failed to read " << kOdsignInfoSignature;
251*e1997b9aSAndroid Build Coastguard Worker }
252*e1997b9aSAndroid Build Coastguard Worker
253*e1997b9aSAndroid Build Coastguard Worker std::fstream odsign_info(kOdsignInfo, std::ios::in | std::ios::binary);
254*e1997b9aSAndroid Build Coastguard Worker if (!odsign_info) {
255*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to open " << kOdsignInfo;
256*e1997b9aSAndroid Build Coastguard Worker }
257*e1997b9aSAndroid Build Coastguard Worker odsign_info.seekg(0);
258*e1997b9aSAndroid Build Coastguard Worker // Verify the hash
259*e1997b9aSAndroid Build Coastguard Worker std::string odsign_info_str((std::istreambuf_iterator<char>(odsign_info)),
260*e1997b9aSAndroid Build Coastguard Worker std::istreambuf_iterator<char>());
261*e1997b9aSAndroid Build Coastguard Worker
262*e1997b9aSAndroid Build Coastguard Worker auto publicKey = key.getPublicKey();
263*e1997b9aSAndroid Build Coastguard Worker auto signResult = verifySignature(odsign_info_str, persistedSignature, *publicKey);
264*e1997b9aSAndroid Build Coastguard Worker if (!signResult.ok()) {
265*e1997b9aSAndroid Build Coastguard Worker return Error() << kOdsignInfoSignature << " does not match.";
266*e1997b9aSAndroid Build Coastguard Worker } else {
267*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << kOdsignInfoSignature << " matches.";
268*e1997b9aSAndroid Build Coastguard Worker }
269*e1997b9aSAndroid Build Coastguard Worker
270*e1997b9aSAndroid Build Coastguard Worker odsign_info.seekg(0);
271*e1997b9aSAndroid Build Coastguard Worker if (!odsignInfo.ParseFromIstream(&odsign_info)) {
272*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to parse " << kOdsignInfo;
273*e1997b9aSAndroid Build Coastguard Worker }
274*e1997b9aSAndroid Build Coastguard Worker
275*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Loaded " << kOdsignInfo;
276*e1997b9aSAndroid Build Coastguard Worker return odsignInfo;
277*e1997b9aSAndroid Build Coastguard Worker }
278*e1997b9aSAndroid Build Coastguard Worker
getTrustedDigests(const SigningKey & key)279*e1997b9aSAndroid Build Coastguard Worker std::map<std::string, std::string> getTrustedDigests(const SigningKey& key) {
280*e1997b9aSAndroid Build Coastguard Worker std::map<std::string, std::string> trusted_digests;
281*e1997b9aSAndroid Build Coastguard Worker
282*e1997b9aSAndroid Build Coastguard Worker if (access(kOdsignInfo.c_str(), F_OK) != 0) {
283*e1997b9aSAndroid Build Coastguard Worker // no odsign info file, which is not necessarily an error - just return
284*e1997b9aSAndroid Build Coastguard Worker // an empty list of digests.
285*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << kOdsignInfo << " not found.";
286*e1997b9aSAndroid Build Coastguard Worker return trusted_digests;
287*e1997b9aSAndroid Build Coastguard Worker }
288*e1997b9aSAndroid Build Coastguard Worker auto signInfo = getAndVerifyOdsignInfo(key);
289*e1997b9aSAndroid Build Coastguard Worker
290*e1997b9aSAndroid Build Coastguard Worker if (signInfo.ok()) {
291*e1997b9aSAndroid Build Coastguard Worker trusted_digests.insert(signInfo->file_hashes().begin(), signInfo->file_hashes().end());
292*e1997b9aSAndroid Build Coastguard Worker } else {
293*e1997b9aSAndroid Build Coastguard Worker // This is not expected, since the file did exist. Log an error and
294*e1997b9aSAndroid Build Coastguard Worker // return an empty list of digests.
295*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Couldn't load trusted digests: " << signInfo.error();
296*e1997b9aSAndroid Build Coastguard Worker }
297*e1997b9aSAndroid Build Coastguard Worker
298*e1997b9aSAndroid Build Coastguard Worker return trusted_digests;
299*e1997b9aSAndroid Build Coastguard Worker }
300*e1997b9aSAndroid Build Coastguard Worker
persistDigests(const std::map<std::string,std::string> & digests,const SigningKey & key)301*e1997b9aSAndroid Build Coastguard Worker Result<void> persistDigests(const std::map<std::string, std::string>& digests,
302*e1997b9aSAndroid Build Coastguard Worker const SigningKey& key) {
303*e1997b9aSAndroid Build Coastguard Worker OdsignInfo signInfo;
304*e1997b9aSAndroid Build Coastguard Worker google::protobuf::Map<std::string, std::string> proto_hashes(digests.begin(), digests.end());
305*e1997b9aSAndroid Build Coastguard Worker auto map = signInfo.mutable_file_hashes();
306*e1997b9aSAndroid Build Coastguard Worker *map = proto_hashes;
307*e1997b9aSAndroid Build Coastguard Worker
308*e1997b9aSAndroid Build Coastguard Worker std::fstream odsign_info(kOdsignInfo,
309*e1997b9aSAndroid Build Coastguard Worker std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
310*e1997b9aSAndroid Build Coastguard Worker if (!signInfo.SerializeToOstream(&odsign_info)) {
311*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to persist root hashes in " << kOdsignInfo;
312*e1997b9aSAndroid Build Coastguard Worker }
313*e1997b9aSAndroid Build Coastguard Worker
314*e1997b9aSAndroid Build Coastguard Worker // Sign the signatures with our key itself, and write that to storage
315*e1997b9aSAndroid Build Coastguard Worker odsign_info.seekg(0, std::ios::beg);
316*e1997b9aSAndroid Build Coastguard Worker std::string odsign_info_str((std::istreambuf_iterator<char>(odsign_info)),
317*e1997b9aSAndroid Build Coastguard Worker std::istreambuf_iterator<char>());
318*e1997b9aSAndroid Build Coastguard Worker auto signResult = key.sign(odsign_info_str);
319*e1997b9aSAndroid Build Coastguard Worker if (!signResult.ok()) {
320*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to sign " << kOdsignInfo;
321*e1997b9aSAndroid Build Coastguard Worker }
322*e1997b9aSAndroid Build Coastguard Worker android::base::WriteStringToFile(*signResult, kOdsignInfoSignature);
323*e1997b9aSAndroid Build Coastguard Worker return {};
324*e1997b9aSAndroid Build Coastguard Worker }
325*e1997b9aSAndroid Build Coastguard Worker
verifyArtifactsIntegrity(const std::map<std::string,std::string> & trusted_digests,bool supportsFsVerity)326*e1997b9aSAndroid Build Coastguard Worker Result<void> verifyArtifactsIntegrity(const std::map<std::string, std::string>& trusted_digests,
327*e1997b9aSAndroid Build Coastguard Worker bool supportsFsVerity) {
328*e1997b9aSAndroid Build Coastguard Worker Result<void> integrityStatus;
329*e1997b9aSAndroid Build Coastguard Worker
330*e1997b9aSAndroid Build Coastguard Worker if (supportsFsVerity) {
331*e1997b9aSAndroid Build Coastguard Worker integrityStatus = verifyIntegrityFsVerity(trusted_digests);
332*e1997b9aSAndroid Build Coastguard Worker } else {
333*e1997b9aSAndroid Build Coastguard Worker integrityStatus = verifyIntegrityNoFsVerity(trusted_digests);
334*e1997b9aSAndroid Build Coastguard Worker }
335*e1997b9aSAndroid Build Coastguard Worker if (!integrityStatus.ok()) {
336*e1997b9aSAndroid Build Coastguard Worker return integrityStatus.error();
337*e1997b9aSAndroid Build Coastguard Worker }
338*e1997b9aSAndroid Build Coastguard Worker
339*e1997b9aSAndroid Build Coastguard Worker return {};
340*e1997b9aSAndroid Build Coastguard Worker }
341*e1997b9aSAndroid Build Coastguard Worker
getComposInfo()342*e1997b9aSAndroid Build Coastguard Worker Result<OdsignInfo> getComposInfo() {
343*e1997b9aSAndroid Build Coastguard Worker const char* const argv[] = {kCompOsVerifyPath, "--instance", "current"};
344*e1997b9aSAndroid Build Coastguard Worker int result =
345*e1997b9aSAndroid Build Coastguard Worker logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
346*e1997b9aSAndroid Build Coastguard Worker if (result != 0) {
347*e1997b9aSAndroid Build Coastguard Worker return Error() << kCompOsVerifyPath << " returned " << result;
348*e1997b9aSAndroid Build Coastguard Worker }
349*e1997b9aSAndroid Build Coastguard Worker
350*e1997b9aSAndroid Build Coastguard Worker std::string compos_info_str;
351*e1997b9aSAndroid Build Coastguard Worker if (!android::base::ReadFileToString(kCompOsInfo, &compos_info_str)) {
352*e1997b9aSAndroid Build Coastguard Worker return ErrnoError() << "Failed to read " << kCompOsInfo;
353*e1997b9aSAndroid Build Coastguard Worker }
354*e1997b9aSAndroid Build Coastguard Worker
355*e1997b9aSAndroid Build Coastguard Worker // Delete the files - we don't need them any more, and they'd confuse
356*e1997b9aSAndroid Build Coastguard Worker // artifact verification
357*e1997b9aSAndroid Build Coastguard Worker if (unlink(kCompOsInfo.c_str()) != 0 || unlink(kCompOsInfoSignature.c_str()) != 0) {
358*e1997b9aSAndroid Build Coastguard Worker return ErrnoError() << "Unable to delete CompOS info/signature file";
359*e1997b9aSAndroid Build Coastguard Worker }
360*e1997b9aSAndroid Build Coastguard Worker
361*e1997b9aSAndroid Build Coastguard Worker OdsignInfo compos_info;
362*e1997b9aSAndroid Build Coastguard Worker if (!compos_info.ParseFromString(compos_info_str)) {
363*e1997b9aSAndroid Build Coastguard Worker return Error() << "Failed to parse " << kCompOsInfo;
364*e1997b9aSAndroid Build Coastguard Worker }
365*e1997b9aSAndroid Build Coastguard Worker
366*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Loaded " << kCompOsInfo;
367*e1997b9aSAndroid Build Coastguard Worker return compos_info;
368*e1997b9aSAndroid Build Coastguard Worker }
369*e1997b9aSAndroid Build Coastguard Worker
CheckCompOsPendingArtifacts(const SigningKey & signing_key,bool * digests_verified,StatsReporter * stats_reporter)370*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode CheckCompOsPendingArtifacts(const SigningKey& signing_key,
371*e1997b9aSAndroid Build Coastguard Worker bool* digests_verified,
372*e1997b9aSAndroid Build Coastguard Worker StatsReporter* stats_reporter) {
373*e1997b9aSAndroid Build Coastguard Worker StatsReporter::CompOsArtifactsCheckRecord* compos_check_record =
374*e1997b9aSAndroid Build Coastguard Worker stats_reporter->GetOrCreateComposArtifactsCheckRecord();
375*e1997b9aSAndroid Build Coastguard Worker
376*e1997b9aSAndroid Build Coastguard Worker if (!directoryHasContent(kCompOsPendingArtifactsDir)) {
377*e1997b9aSAndroid Build Coastguard Worker // No pending CompOS artifacts, all that matters is the current ones.
378*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode odrefresh_status = checkArtifacts();
379*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
380*e1997b9aSAndroid Build Coastguard Worker compos_check_record->current_artifacts_ok = true;
381*e1997b9aSAndroid Build Coastguard Worker }
382*e1997b9aSAndroid Build Coastguard Worker return odrefresh_status;
383*e1997b9aSAndroid Build Coastguard Worker }
384*e1997b9aSAndroid Build Coastguard Worker
385*e1997b9aSAndroid Build Coastguard Worker compos_check_record->comp_os_pending_artifacts_exists = true;
386*e1997b9aSAndroid Build Coastguard Worker
387*e1997b9aSAndroid Build Coastguard Worker // CompOS has generated some artifacts that may, or may not, match the
388*e1997b9aSAndroid Build Coastguard Worker // current state. But if there are already valid artifacts present the
389*e1997b9aSAndroid Build Coastguard Worker // CompOS ones are redundant.
390*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode odrefresh_status = checkArtifacts();
391*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status != art::odrefresh::ExitCode::kCompilationRequired) {
392*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
393*e1997b9aSAndroid Build Coastguard Worker compos_check_record->current_artifacts_ok = true;
394*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Current artifacts are OK, deleting pending artifacts";
395*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kCompOsPendingArtifactsDir);
396*e1997b9aSAndroid Build Coastguard Worker }
397*e1997b9aSAndroid Build Coastguard Worker return odrefresh_status;
398*e1997b9aSAndroid Build Coastguard Worker }
399*e1997b9aSAndroid Build Coastguard Worker
400*e1997b9aSAndroid Build Coastguard Worker // No useful current artifacts, lets see if the CompOS ones are ok
401*e1997b9aSAndroid Build Coastguard Worker if (access(kCompOsPendingInfoPath, R_OK) != 0 ||
402*e1997b9aSAndroid Build Coastguard Worker access(kCompOsPendingInfoSignaturePath, R_OK) != 0) {
403*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Missing CompOS info/signature, deleting pending artifacts";
404*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kCompOsPendingArtifactsDir);
405*e1997b9aSAndroid Build Coastguard Worker return art::odrefresh::ExitCode::kCompilationRequired;
406*e1997b9aSAndroid Build Coastguard Worker }
407*e1997b9aSAndroid Build Coastguard Worker
408*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Current artifacts are out of date, switching to pending artifacts";
409*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kArtArtifactsDir);
410*e1997b9aSAndroid Build Coastguard Worker if (!rename(kCompOsPendingArtifactsDir, kArtArtifactsDir)) {
411*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kCompOsPendingArtifactsDir);
412*e1997b9aSAndroid Build Coastguard Worker return art::odrefresh::ExitCode::kCompilationRequired;
413*e1997b9aSAndroid Build Coastguard Worker }
414*e1997b9aSAndroid Build Coastguard Worker
415*e1997b9aSAndroid Build Coastguard Worker // Make sure the artifacts we have are genuinely produced by the current
416*e1997b9aSAndroid Build Coastguard Worker // instance of CompOS.
417*e1997b9aSAndroid Build Coastguard Worker auto compos_info = getComposInfo();
418*e1997b9aSAndroid Build Coastguard Worker if (!compos_info.ok()) {
419*e1997b9aSAndroid Build Coastguard Worker LOG(WARNING) << compos_info.error();
420*e1997b9aSAndroid Build Coastguard Worker } else {
421*e1997b9aSAndroid Build Coastguard Worker std::map<std::string, std::string> compos_digests(compos_info->file_hashes().begin(),
422*e1997b9aSAndroid Build Coastguard Worker compos_info->file_hashes().end());
423*e1997b9aSAndroid Build Coastguard Worker
424*e1997b9aSAndroid Build Coastguard Worker auto status = verifyAllFilesUsingCompOs(kArtArtifactsDir, compos_digests);
425*e1997b9aSAndroid Build Coastguard Worker if (!status.ok()) {
426*e1997b9aSAndroid Build Coastguard Worker LOG(WARNING) << "Faild to verify CompOS artifacts: " << status.error();
427*e1997b9aSAndroid Build Coastguard Worker } else {
428*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "CompOS artifacts successfully verified.";
429*e1997b9aSAndroid Build Coastguard Worker odrefresh_status = checkArtifacts();
430*e1997b9aSAndroid Build Coastguard Worker switch (odrefresh_status) {
431*e1997b9aSAndroid Build Coastguard Worker case art::odrefresh::ExitCode::kCompilationRequired:
432*e1997b9aSAndroid Build Coastguard Worker // We have verified all the files, and we need to make sure
433*e1997b9aSAndroid Build Coastguard Worker // we don't check them against odsign.info which will be out
434*e1997b9aSAndroid Build Coastguard Worker // of date.
435*e1997b9aSAndroid Build Coastguard Worker *digests_verified = true;
436*e1997b9aSAndroid Build Coastguard Worker return odrefresh_status;
437*e1997b9aSAndroid Build Coastguard Worker case art::odrefresh::ExitCode::kOkay: {
438*e1997b9aSAndroid Build Coastguard Worker // We have digests of all the files, so we can just sign them & save them now.
439*e1997b9aSAndroid Build Coastguard Worker // We need to make sure we don't check them against odsign.info which will
440*e1997b9aSAndroid Build Coastguard Worker // be out of date.
441*e1997b9aSAndroid Build Coastguard Worker auto persisted = persistDigests(compos_digests, signing_key);
442*e1997b9aSAndroid Build Coastguard Worker if (!persisted.ok()) {
443*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << persisted.error();
444*e1997b9aSAndroid Build Coastguard Worker // Don't try to compile again - if we can't write the digests, things
445*e1997b9aSAndroid Build Coastguard Worker // are pretty bad.
446*e1997b9aSAndroid Build Coastguard Worker return art::odrefresh::ExitCode::kCleanupFailed;
447*e1997b9aSAndroid Build Coastguard Worker }
448*e1997b9aSAndroid Build Coastguard Worker compos_check_record->use_comp_os_generated_artifacts = true;
449*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Persisted CompOS digests.";
450*e1997b9aSAndroid Build Coastguard Worker *digests_verified = true;
451*e1997b9aSAndroid Build Coastguard Worker return odrefresh_status;
452*e1997b9aSAndroid Build Coastguard Worker }
453*e1997b9aSAndroid Build Coastguard Worker default:
454*e1997b9aSAndroid Build Coastguard Worker return odrefresh_status;
455*e1997b9aSAndroid Build Coastguard Worker }
456*e1997b9aSAndroid Build Coastguard Worker }
457*e1997b9aSAndroid Build Coastguard Worker }
458*e1997b9aSAndroid Build Coastguard Worker
459*e1997b9aSAndroid Build Coastguard Worker // We can't use the existing artifacts, so we will need to generate new
460*e1997b9aSAndroid Build Coastguard Worker // ones.
461*e1997b9aSAndroid Build Coastguard Worker if (removeDirectory(kArtArtifactsDir) == 0) {
462*e1997b9aSAndroid Build Coastguard Worker // We have unsigned artifacts that we can't delete, so it's not safe to continue.
463*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Unable to delete invalid CompOS artifacts";
464*e1997b9aSAndroid Build Coastguard Worker return art::odrefresh::ExitCode::kCleanupFailed;
465*e1997b9aSAndroid Build Coastguard Worker }
466*e1997b9aSAndroid Build Coastguard Worker
467*e1997b9aSAndroid Build Coastguard Worker return art::odrefresh::ExitCode::kCompilationRequired;
468*e1997b9aSAndroid Build Coastguard Worker }
469*e1997b9aSAndroid Build Coastguard Worker } // namespace
470*e1997b9aSAndroid Build Coastguard Worker
main(int,char ** argv)471*e1997b9aSAndroid Build Coastguard Worker int main(int /* argc */, char** argv) {
472*e1997b9aSAndroid Build Coastguard Worker android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
473*e1997b9aSAndroid Build Coastguard Worker
474*e1997b9aSAndroid Build Coastguard Worker auto scope_guard = android::base::make_scope_guard([]() {
475*e1997b9aSAndroid Build Coastguard Worker // In case we hit any error, remove the artifacts and tell Zygote not to use
476*e1997b9aSAndroid Build Coastguard Worker // anything
477*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kArtArtifactsDir);
478*e1997b9aSAndroid Build Coastguard Worker removeDirectory(kCompOsPendingArtifactsDir);
479*e1997b9aSAndroid Build Coastguard Worker // Tell init we don't need to use our key anymore
480*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignKeyDoneProp, "1");
481*e1997b9aSAndroid Build Coastguard Worker // Tell init we're done with verification, and that it was an error
482*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignVerificationStatusProp, kOdsignVerificationStatusError);
483*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignVerificationDoneProp, "1");
484*e1997b9aSAndroid Build Coastguard Worker // Tell init it shouldn't try to restart us - see odsign.rc
485*e1997b9aSAndroid Build Coastguard Worker SetProperty(kStopServiceProp, "odsign");
486*e1997b9aSAndroid Build Coastguard Worker });
487*e1997b9aSAndroid Build Coastguard Worker
488*e1997b9aSAndroid Build Coastguard Worker // `stats_reporter` must come after `scope_guard` so that its destructor is called before
489*e1997b9aSAndroid Build Coastguard Worker // `scope_guard`.
490*e1997b9aSAndroid Build Coastguard Worker auto stats_reporter = std::make_unique<StatsReporter>();
491*e1997b9aSAndroid Build Coastguard Worker StatsReporter::OdsignRecord* odsign_record = stats_reporter->GetOdsignRecord();
492*e1997b9aSAndroid Build Coastguard Worker
493*e1997b9aSAndroid Build Coastguard Worker if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
494*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Device doesn't support updatable APEX, exiting.";
495*e1997b9aSAndroid Build Coastguard Worker stats_reporter->SetOdsignRecordEnabled(false);
496*e1997b9aSAndroid Build Coastguard Worker return 0;
497*e1997b9aSAndroid Build Coastguard Worker }
498*e1997b9aSAndroid Build Coastguard Worker auto keystoreResult =
499*e1997b9aSAndroid Build Coastguard Worker KeystoreKey::getInstance(kPublicKeySignature, kKeyAlias, kKeyNspace, kKeyBootLevel);
500*e1997b9aSAndroid Build Coastguard Worker if (!keystoreResult.ok()) {
501*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Could not create keystore key: " << keystoreResult.error();
502*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
503*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_KEYSTORE_FAILED;
504*e1997b9aSAndroid Build Coastguard Worker return -1;
505*e1997b9aSAndroid Build Coastguard Worker }
506*e1997b9aSAndroid Build Coastguard Worker SigningKey* key = keystoreResult.value();
507*e1997b9aSAndroid Build Coastguard Worker
508*e1997b9aSAndroid Build Coastguard Worker bool supportsFsVerity = SupportsFsVerity();
509*e1997b9aSAndroid Build Coastguard Worker if (!supportsFsVerity) {
510*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Device doesn't support fsverity. Falling back to full verification.";
511*e1997b9aSAndroid Build Coastguard Worker }
512*e1997b9aSAndroid Build Coastguard Worker
513*e1997b9aSAndroid Build Coastguard Worker bool useCompOs = kUseCompOs && supportsFsVerity && compOsPresent();
514*e1997b9aSAndroid Build Coastguard Worker
515*e1997b9aSAndroid Build Coastguard Worker if (supportsFsVerity) {
516*e1997b9aSAndroid Build Coastguard Worker auto existing_cert = verifyExistingRootCert(*key);
517*e1997b9aSAndroid Build Coastguard Worker if (!existing_cert.ok()) {
518*e1997b9aSAndroid Build Coastguard Worker LOG(WARNING) << existing_cert.error();
519*e1997b9aSAndroid Build Coastguard Worker
520*e1997b9aSAndroid Build Coastguard Worker // Try to create a new cert
521*e1997b9aSAndroid Build Coastguard Worker auto new_cert = createX509RootCert(*key, kSigningKeyCert);
522*e1997b9aSAndroid Build Coastguard Worker if (!new_cert.ok()) {
523*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to create X509 certificate: " << new_cert.error();
524*e1997b9aSAndroid Build Coastguard Worker // TODO apparently the key become invalid - delete the blob / cert
525*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
526*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_CERT_FAILED;
527*e1997b9aSAndroid Build Coastguard Worker return -1;
528*e1997b9aSAndroid Build Coastguard Worker }
529*e1997b9aSAndroid Build Coastguard Worker } else {
530*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Found and verified existing public key certificate: " << kSigningKeyCert;
531*e1997b9aSAndroid Build Coastguard Worker }
532*e1997b9aSAndroid Build Coastguard Worker }
533*e1997b9aSAndroid Build Coastguard Worker
534*e1997b9aSAndroid Build Coastguard Worker bool digests_verified = false;
535*e1997b9aSAndroid Build Coastguard Worker art::odrefresh::ExitCode odrefresh_status =
536*e1997b9aSAndroid Build Coastguard Worker useCompOs ? CheckCompOsPendingArtifacts(*key, &digests_verified, stats_reporter.get())
537*e1997b9aSAndroid Build Coastguard Worker : checkArtifacts();
538*e1997b9aSAndroid Build Coastguard Worker
539*e1997b9aSAndroid Build Coastguard Worker // The artifacts dir doesn't necessarily need to exist; if the existing
540*e1997b9aSAndroid Build Coastguard Worker // artifacts on the system partition are valid, those can be used.
541*e1997b9aSAndroid Build Coastguard Worker int err = access(kArtArtifactsDir.c_str(), F_OK);
542*e1997b9aSAndroid Build Coastguard Worker // If we receive any error other than ENOENT, be suspicious
543*e1997b9aSAndroid Build Coastguard Worker bool artifactsPresent = (err == 0) || (err < 0 && errno != ENOENT);
544*e1997b9aSAndroid Build Coastguard Worker
545*e1997b9aSAndroid Build Coastguard Worker if (artifactsPresent && !digests_verified &&
546*e1997b9aSAndroid Build Coastguard Worker (odrefresh_status == art::odrefresh::ExitCode::kOkay ||
547*e1997b9aSAndroid Build Coastguard Worker odrefresh_status == art::odrefresh::ExitCode::kCompilationRequired)) {
548*e1997b9aSAndroid Build Coastguard Worker // If we haven't verified the digests yet, we need to validate them. We
549*e1997b9aSAndroid Build Coastguard Worker // need to do this both in case the existing artifacts are okay, but
550*e1997b9aSAndroid Build Coastguard Worker // also if odrefresh said that a recompile is required. In the latter
551*e1997b9aSAndroid Build Coastguard Worker // case, odrefresh may use partial compilation, and leave some
552*e1997b9aSAndroid Build Coastguard Worker // artifacts unchanged.
553*e1997b9aSAndroid Build Coastguard Worker auto trusted_digests = getTrustedDigests(*key);
554*e1997b9aSAndroid Build Coastguard Worker
555*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
556*e1997b9aSAndroid Build Coastguard Worker // Tell init we're done with the key; this is a boot time optimization
557*e1997b9aSAndroid Build Coastguard Worker // in particular for the no fs-verity case, where we need to do a
558*e1997b9aSAndroid Build Coastguard Worker // costly verification. If the files haven't been tampered with, which
559*e1997b9aSAndroid Build Coastguard Worker // should be the common path, the verification will succeed, and we won't
560*e1997b9aSAndroid Build Coastguard Worker // need the key anymore. If it turns out the artifacts are invalid (eg not
561*e1997b9aSAndroid Build Coastguard Worker // in fs-verity) or the hash doesn't match, we won't be able to generate
562*e1997b9aSAndroid Build Coastguard Worker // new artifacts without the key, so in those cases, remove the artifacts,
563*e1997b9aSAndroid Build Coastguard Worker // and use JIT zygote for the current boot. We should recover automatically
564*e1997b9aSAndroid Build Coastguard Worker // by the next boot.
565*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignKeyDoneProp, "1");
566*e1997b9aSAndroid Build Coastguard Worker }
567*e1997b9aSAndroid Build Coastguard Worker
568*e1997b9aSAndroid Build Coastguard Worker auto verificationResult = verifyArtifactsIntegrity(trusted_digests, supportsFsVerity);
569*e1997b9aSAndroid Build Coastguard Worker if (!verificationResult.ok()) {
570*e1997b9aSAndroid Build Coastguard Worker int num_removed = removeDirectory(kArtArtifactsDir);
571*e1997b9aSAndroid Build Coastguard Worker if (num_removed == 0) {
572*e1997b9aSAndroid Build Coastguard Worker // If we can't remove the bad artifacts, we shouldn't continue, and
573*e1997b9aSAndroid Build Coastguard Worker // instead prevent Zygote from using them (which is taken care of
574*e1997b9aSAndroid Build Coastguard Worker // in the exit handler).
575*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to remove unknown artifacts.";
576*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
577*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_CLEANUP_FAILED;
578*e1997b9aSAndroid Build Coastguard Worker return -1;
579*e1997b9aSAndroid Build Coastguard Worker }
580*e1997b9aSAndroid Build Coastguard Worker }
581*e1997b9aSAndroid Build Coastguard Worker }
582*e1997b9aSAndroid Build Coastguard Worker
583*e1997b9aSAndroid Build Coastguard Worker // Now that we verified existing artifacts, compile if we need to.
584*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status == art::odrefresh::ExitCode::kCompilationRequired) {
585*e1997b9aSAndroid Build Coastguard Worker odrefresh_status = compileArtifacts(kForceCompilation);
586*e1997b9aSAndroid Build Coastguard Worker }
587*e1997b9aSAndroid Build Coastguard Worker
588*e1997b9aSAndroid Build Coastguard Worker if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
589*e1997b9aSAndroid Build Coastguard Worker // No new artifacts generated, and we verified existing ones above, nothing left to do.
590*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "odrefresh said artifacts are VALID";
591*e1997b9aSAndroid Build Coastguard Worker stats_reporter->SetOdsignRecordEnabled(false);
592*e1997b9aSAndroid Build Coastguard Worker } else if (odrefresh_status == art::odrefresh::ExitCode::kCompilationSuccess ||
593*e1997b9aSAndroid Build Coastguard Worker odrefresh_status == art::odrefresh::ExitCode::kCompilationFailed) {
594*e1997b9aSAndroid Build Coastguard Worker const bool compiled_all = odrefresh_status == art::odrefresh::ExitCode::kCompilationSuccess;
595*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "odrefresh compiled " << (compiled_all ? "all" : "partial")
596*e1997b9aSAndroid Build Coastguard Worker << " artifacts, returned " << odrefresh_status;
597*e1997b9aSAndroid Build Coastguard Worker // This value may be overwritten later.
598*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
599*e1997b9aSAndroid Build Coastguard Worker compiled_all ? art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_ALL_OK
600*e1997b9aSAndroid Build Coastguard Worker : art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_PARTIAL_OK;
601*e1997b9aSAndroid Build Coastguard Worker Result<std::map<std::string, std::string>> digests;
602*e1997b9aSAndroid Build Coastguard Worker if (supportsFsVerity) {
603*e1997b9aSAndroid Build Coastguard Worker digests = addFilesToVerityRecursive(kArtArtifactsDir);
604*e1997b9aSAndroid Build Coastguard Worker } else {
605*e1997b9aSAndroid Build Coastguard Worker // If we can't use verity, just compute the root hashes and store
606*e1997b9aSAndroid Build Coastguard Worker // those, so we can reverify them at the next boot.
607*e1997b9aSAndroid Build Coastguard Worker digests = computeDigests(kArtArtifactsDir);
608*e1997b9aSAndroid Build Coastguard Worker }
609*e1997b9aSAndroid Build Coastguard Worker if (!digests.ok()) {
610*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << digests.error();
611*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
612*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_SIGNING_FAILED;
613*e1997b9aSAndroid Build Coastguard Worker return -1;
614*e1997b9aSAndroid Build Coastguard Worker }
615*e1997b9aSAndroid Build Coastguard Worker auto persistStatus = persistDigests(*digests, *key);
616*e1997b9aSAndroid Build Coastguard Worker if (!persistStatus.ok()) {
617*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << persistStatus.error();
618*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
619*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_SIGNING_FAILED;
620*e1997b9aSAndroid Build Coastguard Worker return -1;
621*e1997b9aSAndroid Build Coastguard Worker }
622*e1997b9aSAndroid Build Coastguard Worker } else if (odrefresh_status == art::odrefresh::ExitCode::kCleanupFailed) {
623*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "odrefresh failed cleaning up existing artifacts";
624*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
625*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_ODREFRESH_FAILED;
626*e1997b9aSAndroid Build Coastguard Worker return -1;
627*e1997b9aSAndroid Build Coastguard Worker } else {
628*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "odrefresh exited unexpectedly, returned " << odrefresh_status;
629*e1997b9aSAndroid Build Coastguard Worker odsign_record->status =
630*e1997b9aSAndroid Build Coastguard Worker art::metrics::statsd::ODSIGN_REPORTED__STATUS__STATUS_ODREFRESH_FAILED;
631*e1997b9aSAndroid Build Coastguard Worker return -1;
632*e1997b9aSAndroid Build Coastguard Worker }
633*e1997b9aSAndroid Build Coastguard Worker
634*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "On-device signing done.";
635*e1997b9aSAndroid Build Coastguard Worker
636*e1997b9aSAndroid Build Coastguard Worker scope_guard.Disable();
637*e1997b9aSAndroid Build Coastguard Worker
638*e1997b9aSAndroid Build Coastguard Worker // Explicitly reset the pointer - We rely on stats_reporter's
639*e1997b9aSAndroid Build Coastguard Worker // destructor for actually writing the buffered metrics. This will otherwise not be called
640*e1997b9aSAndroid Build Coastguard Worker // if the program doesn't exit normally (for ex, killed by init, which actually happens
641*e1997b9aSAndroid Build Coastguard Worker // because odsign (after it finishes) sets kStopServiceProp instructing init to kill it).
642*e1997b9aSAndroid Build Coastguard Worker stats_reporter.reset();
643*e1997b9aSAndroid Build Coastguard Worker
644*e1997b9aSAndroid Build Coastguard Worker // At this point, we're done with the key for sure
645*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignKeyDoneProp, "1");
646*e1997b9aSAndroid Build Coastguard Worker // And we did a successful verification
647*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignVerificationStatusProp, kOdsignVerificationStatusValid);
648*e1997b9aSAndroid Build Coastguard Worker SetProperty(kOdsignVerificationDoneProp, "1");
649*e1997b9aSAndroid Build Coastguard Worker
650*e1997b9aSAndroid Build Coastguard Worker // Tell init it shouldn't try to restart us - see odsign.rc
651*e1997b9aSAndroid Build Coastguard Worker SetProperty(kStopServiceProp, "odsign");
652*e1997b9aSAndroid Build Coastguard Worker return 0;
653*e1997b9aSAndroid Build Coastguard Worker }
654