xref: /aosp_15_r20/system/security/ondevice-signing/odsign_main.cpp (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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