xref: /aosp_15_r20/system/security/identity/CredentialData.cpp (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1*e1997b9aSAndroid Build Coastguard Worker /*
2*e1997b9aSAndroid Build Coastguard Worker  * Copyright (c) 2019, 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 #define LOG_TAG "credstore"
18*e1997b9aSAndroid Build Coastguard Worker 
19*e1997b9aSAndroid Build Coastguard Worker #include <chrono>
20*e1997b9aSAndroid Build Coastguard Worker 
21*e1997b9aSAndroid Build Coastguard Worker #include <fcntl.h>
22*e1997b9aSAndroid Build Coastguard Worker #include <stdlib.h>
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/logging.h>
28*e1997b9aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
29*e1997b9aSAndroid Build Coastguard Worker 
30*e1997b9aSAndroid Build Coastguard Worker #include <cppbor.h>
31*e1997b9aSAndroid Build Coastguard Worker #include <cppbor_parse.h>
32*e1997b9aSAndroid Build Coastguard Worker 
33*e1997b9aSAndroid Build Coastguard Worker #include <android/hardware/identity/support/IdentityCredentialSupport.h>
34*e1997b9aSAndroid Build Coastguard Worker 
35*e1997b9aSAndroid Build Coastguard Worker #include "CredentialData.h"
36*e1997b9aSAndroid Build Coastguard Worker #include "Util.h"
37*e1997b9aSAndroid Build Coastguard Worker 
38*e1997b9aSAndroid Build Coastguard Worker namespace android {
39*e1997b9aSAndroid Build Coastguard Worker namespace security {
40*e1997b9aSAndroid Build Coastguard Worker namespace identity {
41*e1997b9aSAndroid Build Coastguard Worker 
42*e1997b9aSAndroid Build Coastguard Worker using std::optional;
43*e1997b9aSAndroid Build Coastguard Worker 
calculateCredentialFileName(const string & dataPath,uid_t ownerUid,const string & name)44*e1997b9aSAndroid Build Coastguard Worker string CredentialData::calculateCredentialFileName(const string& dataPath, uid_t ownerUid,
45*e1997b9aSAndroid Build Coastguard Worker                                                    const string& name) {
46*e1997b9aSAndroid Build Coastguard Worker     return android::base::StringPrintf(
47*e1997b9aSAndroid Build Coastguard Worker         "%s/%d-%s", dataPath.c_str(), (int)ownerUid,
48*e1997b9aSAndroid Build Coastguard Worker         android::hardware::identity::support::encodeHex(name).c_str());
49*e1997b9aSAndroid Build Coastguard Worker }
50*e1997b9aSAndroid Build Coastguard Worker 
CredentialData(const string & dataPath,uid_t ownerUid,const string & name)51*e1997b9aSAndroid Build Coastguard Worker CredentialData::CredentialData(const string& dataPath, uid_t ownerUid, const string& name)
52*e1997b9aSAndroid Build Coastguard Worker     : dataPath_(dataPath), ownerUid_(ownerUid), name_(name), secureUserId_(0) {
53*e1997b9aSAndroid Build Coastguard Worker     fileName_ = calculateCredentialFileName(dataPath_, ownerUid_, name_);
54*e1997b9aSAndroid Build Coastguard Worker }
55*e1997b9aSAndroid Build Coastguard Worker 
setSecureUserId(int64_t secureUserId)56*e1997b9aSAndroid Build Coastguard Worker void CredentialData::setSecureUserId(int64_t secureUserId) {
57*e1997b9aSAndroid Build Coastguard Worker     secureUserId_ = secureUserId;
58*e1997b9aSAndroid Build Coastguard Worker }
59*e1997b9aSAndroid Build Coastguard Worker 
setCredentialData(const vector<uint8_t> & credentialData)60*e1997b9aSAndroid Build Coastguard Worker void CredentialData::setCredentialData(const vector<uint8_t>& credentialData) {
61*e1997b9aSAndroid Build Coastguard Worker     credentialData_ = credentialData;
62*e1997b9aSAndroid Build Coastguard Worker }
63*e1997b9aSAndroid Build Coastguard Worker 
setAttestationCertificate(const vector<uint8_t> & attestationCertificate)64*e1997b9aSAndroid Build Coastguard Worker void CredentialData::setAttestationCertificate(const vector<uint8_t>& attestationCertificate) {
65*e1997b9aSAndroid Build Coastguard Worker     attestationCertificate_ = attestationCertificate;
66*e1997b9aSAndroid Build Coastguard Worker }
67*e1997b9aSAndroid Build Coastguard Worker 
addSecureAccessControlProfile(const SecureAccessControlProfile & secureAccessControlProfile)68*e1997b9aSAndroid Build Coastguard Worker void CredentialData::addSecureAccessControlProfile(
69*e1997b9aSAndroid Build Coastguard Worker     const SecureAccessControlProfile& secureAccessControlProfile) {
70*e1997b9aSAndroid Build Coastguard Worker     secureAccessControlProfiles_.push_back(secureAccessControlProfile);
71*e1997b9aSAndroid Build Coastguard Worker }
72*e1997b9aSAndroid Build Coastguard Worker 
addEntryData(const string & namespaceName,const string & entryName,const EntryData & data)73*e1997b9aSAndroid Build Coastguard Worker void CredentialData::addEntryData(const string& namespaceName, const string& entryName,
74*e1997b9aSAndroid Build Coastguard Worker                                   const EntryData& data) {
75*e1997b9aSAndroid Build Coastguard Worker     idToEncryptedChunks_[namespaceName + ":" + entryName] = data;
76*e1997b9aSAndroid Build Coastguard Worker }
77*e1997b9aSAndroid Build Coastguard Worker 
saveToDisk() const78*e1997b9aSAndroid Build Coastguard Worker bool CredentialData::saveToDisk() const {
79*e1997b9aSAndroid Build Coastguard Worker     cppbor::Map map;
80*e1997b9aSAndroid Build Coastguard Worker 
81*e1997b9aSAndroid Build Coastguard Worker     map.add("secureUserId", secureUserId_);
82*e1997b9aSAndroid Build Coastguard Worker 
83*e1997b9aSAndroid Build Coastguard Worker     map.add("credentialData", credentialData_);
84*e1997b9aSAndroid Build Coastguard Worker 
85*e1997b9aSAndroid Build Coastguard Worker     map.add("attestationCertificate", attestationCertificate_);
86*e1997b9aSAndroid Build Coastguard Worker 
87*e1997b9aSAndroid Build Coastguard Worker     cppbor::Array sacpArray;
88*e1997b9aSAndroid Build Coastguard Worker     for (const SecureAccessControlProfile& sacp : secureAccessControlProfiles_) {
89*e1997b9aSAndroid Build Coastguard Worker         cppbor::Array array;
90*e1997b9aSAndroid Build Coastguard Worker         array.add(sacp.id);
91*e1997b9aSAndroid Build Coastguard Worker         array.add(sacp.readerCertificate.encodedCertificate);
92*e1997b9aSAndroid Build Coastguard Worker         array.add(sacp.userAuthenticationRequired);
93*e1997b9aSAndroid Build Coastguard Worker         array.add(sacp.timeoutMillis);
94*e1997b9aSAndroid Build Coastguard Worker         array.add(sacp.secureUserId);
95*e1997b9aSAndroid Build Coastguard Worker         vector<uint8_t> mac = sacp.mac;
96*e1997b9aSAndroid Build Coastguard Worker         array.add(mac);
97*e1997b9aSAndroid Build Coastguard Worker         sacpArray.add(std::move(array));
98*e1997b9aSAndroid Build Coastguard Worker     }
99*e1997b9aSAndroid Build Coastguard Worker     map.add("secureAccessControlProfiles", std::move(sacpArray));
100*e1997b9aSAndroid Build Coastguard Worker 
101*e1997b9aSAndroid Build Coastguard Worker     cppbor::Map encryptedBlobsMap;
102*e1997b9aSAndroid Build Coastguard Worker     for (auto const& [nsAndName, entryData] : idToEncryptedChunks_) {
103*e1997b9aSAndroid Build Coastguard Worker         cppbor::Array encryptedChunkArray;
104*e1997b9aSAndroid Build Coastguard Worker         for (const vector<uint8_t>& encryptedChunk : entryData.encryptedChunks) {
105*e1997b9aSAndroid Build Coastguard Worker             encryptedChunkArray.add(encryptedChunk);
106*e1997b9aSAndroid Build Coastguard Worker         }
107*e1997b9aSAndroid Build Coastguard Worker         cppbor::Array entryDataArray;
108*e1997b9aSAndroid Build Coastguard Worker         entryDataArray.add(entryData.size);
109*e1997b9aSAndroid Build Coastguard Worker         cppbor::Array idsArray;
110*e1997b9aSAndroid Build Coastguard Worker         for (int32_t id : entryData.accessControlProfileIds) {
111*e1997b9aSAndroid Build Coastguard Worker             idsArray.add(id);
112*e1997b9aSAndroid Build Coastguard Worker         }
113*e1997b9aSAndroid Build Coastguard Worker         entryDataArray.add(std::move(idsArray));
114*e1997b9aSAndroid Build Coastguard Worker         entryDataArray.add(std::move(encryptedChunkArray));
115*e1997b9aSAndroid Build Coastguard Worker         encryptedBlobsMap.add(nsAndName, std::move(entryDataArray));
116*e1997b9aSAndroid Build Coastguard Worker     }
117*e1997b9aSAndroid Build Coastguard Worker     map.add("entryData", std::move(encryptedBlobsMap));
118*e1997b9aSAndroid Build Coastguard Worker     map.add("authKeyCount", keyCount_);
119*e1997b9aSAndroid Build Coastguard Worker     map.add("maxUsesPerAuthKey", maxUsesPerKey_);
120*e1997b9aSAndroid Build Coastguard Worker     map.add("minValidTimeMillis", minValidTimeMillis_);
121*e1997b9aSAndroid Build Coastguard Worker 
122*e1997b9aSAndroid Build Coastguard Worker     cppbor::Array authKeyDatasArray;
123*e1997b9aSAndroid Build Coastguard Worker     for (const AuthKeyData& data : authKeyDatas_) {
124*e1997b9aSAndroid Build Coastguard Worker         cppbor::Array array;
125*e1997b9aSAndroid Build Coastguard Worker         // Fields 0-6 was in the original version in Android 11
126*e1997b9aSAndroid Build Coastguard Worker         array.add(data.certificate);
127*e1997b9aSAndroid Build Coastguard Worker         array.add(data.keyBlob);
128*e1997b9aSAndroid Build Coastguard Worker         array.add(data.staticAuthenticationData);
129*e1997b9aSAndroid Build Coastguard Worker         array.add(data.pendingCertificate);
130*e1997b9aSAndroid Build Coastguard Worker         array.add(data.pendingKeyBlob);
131*e1997b9aSAndroid Build Coastguard Worker         array.add(data.useCount);
132*e1997b9aSAndroid Build Coastguard Worker         // Field 7 was added in Android 12
133*e1997b9aSAndroid Build Coastguard Worker         array.add(data.expirationDateMillisSinceEpoch);
134*e1997b9aSAndroid Build Coastguard Worker         authKeyDatasArray.add(std::move(array));
135*e1997b9aSAndroid Build Coastguard Worker     }
136*e1997b9aSAndroid Build Coastguard Worker     map.add("authKeyData", std::move(authKeyDatasArray));
137*e1997b9aSAndroid Build Coastguard Worker 
138*e1997b9aSAndroid Build Coastguard Worker     vector<uint8_t> credentialData = map.encode();
139*e1997b9aSAndroid Build Coastguard Worker 
140*e1997b9aSAndroid Build Coastguard Worker     return fileSetContents(fileName_, credentialData);
141*e1997b9aSAndroid Build Coastguard Worker }
142*e1997b9aSAndroid Build Coastguard Worker 
parseSacp(const cppbor::Item & item)143*e1997b9aSAndroid Build Coastguard Worker optional<SecureAccessControlProfile> parseSacp(const cppbor::Item& item) {
144*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Array* array = item.asArray();
145*e1997b9aSAndroid Build Coastguard Worker     if (array == nullptr || array->size() < 6) {
146*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "The SACP CBOR is not an array with at least six elements (size="
147*e1997b9aSAndroid Build Coastguard Worker                    << (array != nullptr ? array->size() : -1) << ")";
148*e1997b9aSAndroid Build Coastguard Worker         return {};
149*e1997b9aSAndroid Build Coastguard Worker     }
150*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Int* itemId = ((*array)[0])->asInt();
151*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemReaderCertificate = ((*array)[1])->asBstr();
152*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Simple* simple = ((*array)[2])->asSimple();
153*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bool* itemUserAuthenticationRequired =
154*e1997b9aSAndroid Build Coastguard Worker         (simple != nullptr ? (simple->asBool()) : nullptr);
155*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Int* itemTimeoutMillis = ((*array)[3])->asInt();
156*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Int* itesecureUserId_ = ((*array)[4])->asInt();
157*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemMac = ((*array)[5])->asBstr();
158*e1997b9aSAndroid Build Coastguard Worker     if (itemId == nullptr || itemReaderCertificate == nullptr ||
159*e1997b9aSAndroid Build Coastguard Worker         itemUserAuthenticationRequired == nullptr || itemTimeoutMillis == nullptr ||
160*e1997b9aSAndroid Build Coastguard Worker         itesecureUserId_ == nullptr || itemMac == nullptr) {
161*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "One or more items SACP array in CBOR is of wrong type";
162*e1997b9aSAndroid Build Coastguard Worker         return {};
163*e1997b9aSAndroid Build Coastguard Worker     }
164*e1997b9aSAndroid Build Coastguard Worker     SecureAccessControlProfile sacp;
165*e1997b9aSAndroid Build Coastguard Worker     sacp.id = itemId->value();
166*e1997b9aSAndroid Build Coastguard Worker     sacp.readerCertificate.encodedCertificate = itemReaderCertificate->value();
167*e1997b9aSAndroid Build Coastguard Worker     sacp.userAuthenticationRequired = itemUserAuthenticationRequired->value();
168*e1997b9aSAndroid Build Coastguard Worker     sacp.timeoutMillis = itemTimeoutMillis->value();
169*e1997b9aSAndroid Build Coastguard Worker     sacp.secureUserId = itesecureUserId_->value();
170*e1997b9aSAndroid Build Coastguard Worker     sacp.mac = itemMac->value();
171*e1997b9aSAndroid Build Coastguard Worker     return sacp;
172*e1997b9aSAndroid Build Coastguard Worker }
173*e1997b9aSAndroid Build Coastguard Worker 
parseAuthKeyData(const cppbor::Item & item)174*e1997b9aSAndroid Build Coastguard Worker optional<AuthKeyData> parseAuthKeyData(const cppbor::Item& item) {
175*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Array* array = item.asArray();
176*e1997b9aSAndroid Build Coastguard Worker     if (array == nullptr || array->size() < 6) {
177*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "The AuthKeyData CBOR is not an array with at least six elements";
178*e1997b9aSAndroid Build Coastguard Worker         return {};
179*e1997b9aSAndroid Build Coastguard Worker     }
180*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemCertificate = ((*array)[0])->asBstr();
181*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemKeyBlob = ((*array)[1])->asBstr();
182*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemStaticAuthenticationData = ((*array)[2])->asBstr();
183*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemPendingCertificate = ((*array)[3])->asBstr();
184*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Bstr* itemPendingKeyBlob = ((*array)[4])->asBstr();
185*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Int* itemUseCount = ((*array)[5])->asInt();
186*e1997b9aSAndroid Build Coastguard Worker     if (itemCertificate == nullptr || itemKeyBlob == nullptr ||
187*e1997b9aSAndroid Build Coastguard Worker         itemStaticAuthenticationData == nullptr || itemPendingCertificate == nullptr ||
188*e1997b9aSAndroid Build Coastguard Worker         itemPendingKeyBlob == nullptr || itemUseCount == nullptr) {
189*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "One or more items in AuthKeyData array in CBOR is of wrong type";
190*e1997b9aSAndroid Build Coastguard Worker         return {};
191*e1997b9aSAndroid Build Coastguard Worker     }
192*e1997b9aSAndroid Build Coastguard Worker     // expirationDateMillisSinceEpoch was added as the 7th element for Android 12. If not
193*e1997b9aSAndroid Build Coastguard Worker     // present, default to longest possible expiration date.
194*e1997b9aSAndroid Build Coastguard Worker     int64_t expirationDateMillisSinceEpoch = INT64_MAX;
195*e1997b9aSAndroid Build Coastguard Worker     if (array->size() >= 7) {
196*e1997b9aSAndroid Build Coastguard Worker         const cppbor::Int* itemExpirationDateMillisSinceEpoch = ((*array)[6])->asInt();
197*e1997b9aSAndroid Build Coastguard Worker         expirationDateMillisSinceEpoch = itemExpirationDateMillisSinceEpoch->value();
198*e1997b9aSAndroid Build Coastguard Worker     }
199*e1997b9aSAndroid Build Coastguard Worker     AuthKeyData authKeyData;
200*e1997b9aSAndroid Build Coastguard Worker     authKeyData.certificate = itemCertificate->value();
201*e1997b9aSAndroid Build Coastguard Worker     authKeyData.keyBlob = itemKeyBlob->value();
202*e1997b9aSAndroid Build Coastguard Worker     authKeyData.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
203*e1997b9aSAndroid Build Coastguard Worker     authKeyData.staticAuthenticationData = itemStaticAuthenticationData->value();
204*e1997b9aSAndroid Build Coastguard Worker     authKeyData.pendingCertificate = itemPendingCertificate->value();
205*e1997b9aSAndroid Build Coastguard Worker     authKeyData.pendingKeyBlob = itemPendingKeyBlob->value();
206*e1997b9aSAndroid Build Coastguard Worker     authKeyData.useCount = itemUseCount->value();
207*e1997b9aSAndroid Build Coastguard Worker     return authKeyData;
208*e1997b9aSAndroid Build Coastguard Worker }
209*e1997b9aSAndroid Build Coastguard Worker 
parseAccessControlProfileIds(const cppbor::Item & item)210*e1997b9aSAndroid Build Coastguard Worker vector<int32_t> parseAccessControlProfileIds(const cppbor::Item& item) {
211*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Array* array = item.asArray();
212*e1997b9aSAndroid Build Coastguard Worker     if (array == nullptr) {
213*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "The accessControlProfileIds member is not an array";
214*e1997b9aSAndroid Build Coastguard Worker         return {};
215*e1997b9aSAndroid Build Coastguard Worker     }
216*e1997b9aSAndroid Build Coastguard Worker 
217*e1997b9aSAndroid Build Coastguard Worker     vector<int32_t> accessControlProfileIds;
218*e1997b9aSAndroid Build Coastguard Worker     for (size_t n = 0; n < array->size(); n++) {
219*e1997b9aSAndroid Build Coastguard Worker         const cppbor::Int* itemInt = ((*array)[n])->asInt();
220*e1997b9aSAndroid Build Coastguard Worker         if (itemInt == nullptr) {
221*e1997b9aSAndroid Build Coastguard Worker             LOG(ERROR) << "An item in the accessControlProfileIds array is not a bstr";
222*e1997b9aSAndroid Build Coastguard Worker             return {};
223*e1997b9aSAndroid Build Coastguard Worker         }
224*e1997b9aSAndroid Build Coastguard Worker         accessControlProfileIds.push_back(itemInt->value());
225*e1997b9aSAndroid Build Coastguard Worker     }
226*e1997b9aSAndroid Build Coastguard Worker     return accessControlProfileIds;
227*e1997b9aSAndroid Build Coastguard Worker }
228*e1997b9aSAndroid Build Coastguard Worker 
parseEncryptedChunks(const cppbor::Item & item)229*e1997b9aSAndroid Build Coastguard Worker optional<vector<vector<uint8_t>>> parseEncryptedChunks(const cppbor::Item& item) {
230*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Array* array = item.asArray();
231*e1997b9aSAndroid Build Coastguard Worker     if (array == nullptr) {
232*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "The encryptedChunks member is not an array";
233*e1997b9aSAndroid Build Coastguard Worker         return {};
234*e1997b9aSAndroid Build Coastguard Worker     }
235*e1997b9aSAndroid Build Coastguard Worker 
236*e1997b9aSAndroid Build Coastguard Worker     vector<vector<uint8_t>> encryptedChunks;
237*e1997b9aSAndroid Build Coastguard Worker     for (size_t n = 0; n < array->size(); n++) {
238*e1997b9aSAndroid Build Coastguard Worker         const cppbor::Bstr* itemBstr = ((*array)[n])->asBstr();
239*e1997b9aSAndroid Build Coastguard Worker         if (itemBstr == nullptr) {
240*e1997b9aSAndroid Build Coastguard Worker             LOG(ERROR) << "An item in the encryptedChunks array is not a bstr";
241*e1997b9aSAndroid Build Coastguard Worker             return {};
242*e1997b9aSAndroid Build Coastguard Worker         }
243*e1997b9aSAndroid Build Coastguard Worker         encryptedChunks.push_back(itemBstr->value());
244*e1997b9aSAndroid Build Coastguard Worker     }
245*e1997b9aSAndroid Build Coastguard Worker     return encryptedChunks;
246*e1997b9aSAndroid Build Coastguard Worker }
247*e1997b9aSAndroid Build Coastguard Worker 
loadFromDisk()248*e1997b9aSAndroid Build Coastguard Worker bool CredentialData::loadFromDisk() {
249*e1997b9aSAndroid Build Coastguard Worker     // Reset all data.
250*e1997b9aSAndroid Build Coastguard Worker     credentialData_.clear();
251*e1997b9aSAndroid Build Coastguard Worker     attestationCertificate_.clear();
252*e1997b9aSAndroid Build Coastguard Worker     secureAccessControlProfiles_.clear();
253*e1997b9aSAndroid Build Coastguard Worker     idToEncryptedChunks_.clear();
254*e1997b9aSAndroid Build Coastguard Worker     authKeyDatas_.clear();
255*e1997b9aSAndroid Build Coastguard Worker     keyCount_ = 0;
256*e1997b9aSAndroid Build Coastguard Worker     maxUsesPerKey_ = 1;
257*e1997b9aSAndroid Build Coastguard Worker     minValidTimeMillis_ = 0;
258*e1997b9aSAndroid Build Coastguard Worker 
259*e1997b9aSAndroid Build Coastguard Worker     optional<vector<uint8_t>> data = fileGetContents(fileName_);
260*e1997b9aSAndroid Build Coastguard Worker     if (!data) {
261*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Error loading data";
262*e1997b9aSAndroid Build Coastguard Worker         return false;
263*e1997b9aSAndroid Build Coastguard Worker     }
264*e1997b9aSAndroid Build Coastguard Worker 
265*e1997b9aSAndroid Build Coastguard Worker     auto [item, _ /* newPos */, message] = cppbor::parse(data.value());
266*e1997b9aSAndroid Build Coastguard Worker     if (item == nullptr) {
267*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Data loaded from " << fileName_ << " is not valid CBOR: " << message;
268*e1997b9aSAndroid Build Coastguard Worker         return false;
269*e1997b9aSAndroid Build Coastguard Worker     }
270*e1997b9aSAndroid Build Coastguard Worker 
271*e1997b9aSAndroid Build Coastguard Worker     const cppbor::Map* map = item->asMap();
272*e1997b9aSAndroid Build Coastguard Worker     if (map == nullptr) {
273*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Top-level item is not a map";
274*e1997b9aSAndroid Build Coastguard Worker         return false;
275*e1997b9aSAndroid Build Coastguard Worker     }
276*e1997b9aSAndroid Build Coastguard Worker 
277*e1997b9aSAndroid Build Coastguard Worker     for (size_t n = 0; n < map->size(); n++) {
278*e1997b9aSAndroid Build Coastguard Worker         auto& [keyItem, valueItem] = (*map)[n];
279*e1997b9aSAndroid Build Coastguard Worker         const cppbor::Tstr* tstr = keyItem->asTstr();
280*e1997b9aSAndroid Build Coastguard Worker         if (tstr == nullptr) {
281*e1997b9aSAndroid Build Coastguard Worker             LOG(ERROR) << "Key item in top-level map is not a tstr";
282*e1997b9aSAndroid Build Coastguard Worker             return false;
283*e1997b9aSAndroid Build Coastguard Worker         }
284*e1997b9aSAndroid Build Coastguard Worker         const string& key = tstr->value();
285*e1997b9aSAndroid Build Coastguard Worker 
286*e1997b9aSAndroid Build Coastguard Worker         if (key == "secureUserId") {
287*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Int* number = valueItem->asInt();
288*e1997b9aSAndroid Build Coastguard Worker             if (number == nullptr) {
289*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for secureUserId is not a number";
290*e1997b9aSAndroid Build Coastguard Worker                 return false;
291*e1997b9aSAndroid Build Coastguard Worker             }
292*e1997b9aSAndroid Build Coastguard Worker             secureUserId_ = number->value();
293*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "credentialData") {
294*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Bstr* valueBstr = valueItem->asBstr();
295*e1997b9aSAndroid Build Coastguard Worker             if (valueBstr == nullptr) {
296*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for credentialData is not a bstr";
297*e1997b9aSAndroid Build Coastguard Worker                 return false;
298*e1997b9aSAndroid Build Coastguard Worker             }
299*e1997b9aSAndroid Build Coastguard Worker             credentialData_ = valueBstr->value();
300*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "attestationCertificate") {
301*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Bstr* valueBstr = valueItem->asBstr();
302*e1997b9aSAndroid Build Coastguard Worker             if (valueBstr == nullptr) {
303*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for attestationCertificate is not a bstr";
304*e1997b9aSAndroid Build Coastguard Worker                 return false;
305*e1997b9aSAndroid Build Coastguard Worker             }
306*e1997b9aSAndroid Build Coastguard Worker             attestationCertificate_ = valueBstr->value();
307*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "secureAccessControlProfiles") {
308*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Array* array = valueItem->asArray();
309*e1997b9aSAndroid Build Coastguard Worker             if (array == nullptr) {
310*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for attestationCertificate is not an array";
311*e1997b9aSAndroid Build Coastguard Worker                 return false;
312*e1997b9aSAndroid Build Coastguard Worker             }
313*e1997b9aSAndroid Build Coastguard Worker             for (size_t m = 0; m < array->size(); m++) {
314*e1997b9aSAndroid Build Coastguard Worker                 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
315*e1997b9aSAndroid Build Coastguard Worker                 optional<SecureAccessControlProfile> sacp = parseSacp(*item);
316*e1997b9aSAndroid Build Coastguard Worker                 if (!sacp) {
317*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Error parsing SecureAccessControlProfile";
318*e1997b9aSAndroid Build Coastguard Worker                     return false;
319*e1997b9aSAndroid Build Coastguard Worker                 }
320*e1997b9aSAndroid Build Coastguard Worker                 secureAccessControlProfiles_.push_back(sacp.value());
321*e1997b9aSAndroid Build Coastguard Worker             }
322*e1997b9aSAndroid Build Coastguard Worker 
323*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "entryData") {
324*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Map* map = valueItem->asMap();
325*e1997b9aSAndroid Build Coastguard Worker             if (map == nullptr) {
326*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for encryptedChunks is not an map";
327*e1997b9aSAndroid Build Coastguard Worker                 return false;
328*e1997b9aSAndroid Build Coastguard Worker             }
329*e1997b9aSAndroid Build Coastguard Worker             for (size_t m = 0; m < map->size(); m++) {
330*e1997b9aSAndroid Build Coastguard Worker                 auto& [ecKeyItem, ecValueItem] = (*map)[m];
331*e1997b9aSAndroid Build Coastguard Worker                 const cppbor::Tstr* ecTstr = ecKeyItem->asTstr();
332*e1997b9aSAndroid Build Coastguard Worker                 if (ecTstr == nullptr) {
333*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Key item in encryptedChunks map is not a tstr";
334*e1997b9aSAndroid Build Coastguard Worker                     return false;
335*e1997b9aSAndroid Build Coastguard Worker                 }
336*e1997b9aSAndroid Build Coastguard Worker                 const string& ecId = ecTstr->value();
337*e1997b9aSAndroid Build Coastguard Worker 
338*e1997b9aSAndroid Build Coastguard Worker                 const cppbor::Array* ecEntryArrayItem = ecValueItem->asArray();
339*e1997b9aSAndroid Build Coastguard Worker                 if (ecEntryArrayItem == nullptr || ecEntryArrayItem->size() < 3) {
340*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Value item in encryptedChunks map is an array with at least two "
341*e1997b9aSAndroid Build Coastguard Worker                                   "elements";
342*e1997b9aSAndroid Build Coastguard Worker                     return false;
343*e1997b9aSAndroid Build Coastguard Worker                 }
344*e1997b9aSAndroid Build Coastguard Worker                 const cppbor::Int* ecEntrySizeItem = (*ecEntryArrayItem)[0]->asInt();
345*e1997b9aSAndroid Build Coastguard Worker                 if (ecEntrySizeItem == nullptr) {
346*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Entry size not a number";
347*e1997b9aSAndroid Build Coastguard Worker                     return false;
348*e1997b9aSAndroid Build Coastguard Worker                 }
349*e1997b9aSAndroid Build Coastguard Worker                 uint64_t entrySize = ecEntrySizeItem->value();
350*e1997b9aSAndroid Build Coastguard Worker 
351*e1997b9aSAndroid Build Coastguard Worker                 optional<vector<int32_t>> accessControlProfileIds =
352*e1997b9aSAndroid Build Coastguard Worker                     parseAccessControlProfileIds(*(*ecEntryArrayItem)[1]);
353*e1997b9aSAndroid Build Coastguard Worker                 if (!accessControlProfileIds) {
354*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Error parsing access control profile ids";
355*e1997b9aSAndroid Build Coastguard Worker                     return false;
356*e1997b9aSAndroid Build Coastguard Worker                 }
357*e1997b9aSAndroid Build Coastguard Worker 
358*e1997b9aSAndroid Build Coastguard Worker                 optional<vector<vector<uint8_t>>> encryptedChunks =
359*e1997b9aSAndroid Build Coastguard Worker                     parseEncryptedChunks(*(*ecEntryArrayItem)[2]);
360*e1997b9aSAndroid Build Coastguard Worker                 if (!encryptedChunks) {
361*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Error parsing encrypted chunks";
362*e1997b9aSAndroid Build Coastguard Worker                     return false;
363*e1997b9aSAndroid Build Coastguard Worker                 }
364*e1997b9aSAndroid Build Coastguard Worker 
365*e1997b9aSAndroid Build Coastguard Worker                 EntryData data;
366*e1997b9aSAndroid Build Coastguard Worker                 data.size = entrySize;
367*e1997b9aSAndroid Build Coastguard Worker                 data.accessControlProfileIds = accessControlProfileIds.value();
368*e1997b9aSAndroid Build Coastguard Worker                 data.encryptedChunks = encryptedChunks.value();
369*e1997b9aSAndroid Build Coastguard Worker                 idToEncryptedChunks_[ecId] = data;
370*e1997b9aSAndroid Build Coastguard Worker             }
371*e1997b9aSAndroid Build Coastguard Worker 
372*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "authKeyData") {
373*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Array* array = valueItem->asArray();
374*e1997b9aSAndroid Build Coastguard Worker             if (array == nullptr) {
375*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for authData is not an array";
376*e1997b9aSAndroid Build Coastguard Worker                 return false;
377*e1997b9aSAndroid Build Coastguard Worker             }
378*e1997b9aSAndroid Build Coastguard Worker             for (size_t m = 0; m < array->size(); m++) {
379*e1997b9aSAndroid Build Coastguard Worker                 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
380*e1997b9aSAndroid Build Coastguard Worker                 optional<AuthKeyData> authKeyData = parseAuthKeyData(*item);
381*e1997b9aSAndroid Build Coastguard Worker                 if (!authKeyData) {
382*e1997b9aSAndroid Build Coastguard Worker                     LOG(ERROR) << "Error parsing AuthKeyData";
383*e1997b9aSAndroid Build Coastguard Worker                     return false;
384*e1997b9aSAndroid Build Coastguard Worker                 }
385*e1997b9aSAndroid Build Coastguard Worker                 authKeyDatas_.push_back(authKeyData.value());
386*e1997b9aSAndroid Build Coastguard Worker             }
387*e1997b9aSAndroid Build Coastguard Worker 
388*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "authKeyCount") {
389*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Int* number = valueItem->asInt();
390*e1997b9aSAndroid Build Coastguard Worker             if (number == nullptr) {
391*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for authKeyCount is not a number";
392*e1997b9aSAndroid Build Coastguard Worker                 return false;
393*e1997b9aSAndroid Build Coastguard Worker             }
394*e1997b9aSAndroid Build Coastguard Worker             keyCount_ = number->value();
395*e1997b9aSAndroid Build Coastguard Worker 
396*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "maxUsesPerAuthKey") {
397*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Int* number = valueItem->asInt();
398*e1997b9aSAndroid Build Coastguard Worker             if (number == nullptr) {
399*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for maxUsesPerAuthKey is not a number";
400*e1997b9aSAndroid Build Coastguard Worker                 return false;
401*e1997b9aSAndroid Build Coastguard Worker             }
402*e1997b9aSAndroid Build Coastguard Worker             maxUsesPerKey_ = number->value();
403*e1997b9aSAndroid Build Coastguard Worker 
404*e1997b9aSAndroid Build Coastguard Worker         } else if (key == "minValidTimeMillis") {
405*e1997b9aSAndroid Build Coastguard Worker             const cppbor::Int* number = valueItem->asInt();
406*e1997b9aSAndroid Build Coastguard Worker             if (number == nullptr) {
407*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Value for minValidTimeMillis is not a number";
408*e1997b9aSAndroid Build Coastguard Worker                 return false;
409*e1997b9aSAndroid Build Coastguard Worker             }
410*e1997b9aSAndroid Build Coastguard Worker             minValidTimeMillis_ = number->value();
411*e1997b9aSAndroid Build Coastguard Worker         }
412*e1997b9aSAndroid Build Coastguard Worker     }
413*e1997b9aSAndroid Build Coastguard Worker 
414*e1997b9aSAndroid Build Coastguard Worker     if (credentialData_.size() == 0) {
415*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Missing credentialData";
416*e1997b9aSAndroid Build Coastguard Worker         return false;
417*e1997b9aSAndroid Build Coastguard Worker     }
418*e1997b9aSAndroid Build Coastguard Worker 
419*e1997b9aSAndroid Build Coastguard Worker     if (attestationCertificate_.size() == 0) {
420*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Missing attestationCertificate";
421*e1997b9aSAndroid Build Coastguard Worker         return false;
422*e1997b9aSAndroid Build Coastguard Worker     }
423*e1997b9aSAndroid Build Coastguard Worker 
424*e1997b9aSAndroid Build Coastguard Worker     if (size_t(keyCount_) != authKeyDatas_.size()) {
425*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "keyCount_=" << keyCount_
426*e1997b9aSAndroid Build Coastguard Worker                    << " != authKeyDatas_.size()=" << authKeyDatas_.size();
427*e1997b9aSAndroid Build Coastguard Worker         return false;
428*e1997b9aSAndroid Build Coastguard Worker     }
429*e1997b9aSAndroid Build Coastguard Worker 
430*e1997b9aSAndroid Build Coastguard Worker     return true;
431*e1997b9aSAndroid Build Coastguard Worker }
432*e1997b9aSAndroid Build Coastguard Worker 
getCredentialData() const433*e1997b9aSAndroid Build Coastguard Worker const vector<uint8_t>& CredentialData::getCredentialData() const {
434*e1997b9aSAndroid Build Coastguard Worker     return credentialData_;
435*e1997b9aSAndroid Build Coastguard Worker }
436*e1997b9aSAndroid Build Coastguard Worker 
getSecureUserId()437*e1997b9aSAndroid Build Coastguard Worker int64_t CredentialData::getSecureUserId() {
438*e1997b9aSAndroid Build Coastguard Worker     return secureUserId_;
439*e1997b9aSAndroid Build Coastguard Worker }
440*e1997b9aSAndroid Build Coastguard Worker 
getAttestationCertificate() const441*e1997b9aSAndroid Build Coastguard Worker const vector<uint8_t>& CredentialData::getAttestationCertificate() const {
442*e1997b9aSAndroid Build Coastguard Worker     return attestationCertificate_;
443*e1997b9aSAndroid Build Coastguard Worker }
444*e1997b9aSAndroid Build Coastguard Worker 
getSecureAccessControlProfiles() const445*e1997b9aSAndroid Build Coastguard Worker const vector<SecureAccessControlProfile>& CredentialData::getSecureAccessControlProfiles() const {
446*e1997b9aSAndroid Build Coastguard Worker     return secureAccessControlProfiles_;
447*e1997b9aSAndroid Build Coastguard Worker }
448*e1997b9aSAndroid Build Coastguard Worker 
hasEntryData(const string & namespaceName,const string & entryName) const449*e1997b9aSAndroid Build Coastguard Worker bool CredentialData::hasEntryData(const string& namespaceName, const string& entryName) const {
450*e1997b9aSAndroid Build Coastguard Worker     string id = namespaceName + ":" + entryName;
451*e1997b9aSAndroid Build Coastguard Worker     auto iter = idToEncryptedChunks_.find(id);
452*e1997b9aSAndroid Build Coastguard Worker     if (iter == idToEncryptedChunks_.end()) {
453*e1997b9aSAndroid Build Coastguard Worker         return false;
454*e1997b9aSAndroid Build Coastguard Worker     }
455*e1997b9aSAndroid Build Coastguard Worker     return true;
456*e1997b9aSAndroid Build Coastguard Worker }
457*e1997b9aSAndroid Build Coastguard Worker 
getEntryData(const string & namespaceName,const string & entryName) const458*e1997b9aSAndroid Build Coastguard Worker optional<EntryData> CredentialData::getEntryData(const string& namespaceName,
459*e1997b9aSAndroid Build Coastguard Worker                                                  const string& entryName) const {
460*e1997b9aSAndroid Build Coastguard Worker     string id = namespaceName + ":" + entryName;
461*e1997b9aSAndroid Build Coastguard Worker     auto iter = idToEncryptedChunks_.find(id);
462*e1997b9aSAndroid Build Coastguard Worker     if (iter == idToEncryptedChunks_.end()) {
463*e1997b9aSAndroid Build Coastguard Worker         return {};
464*e1997b9aSAndroid Build Coastguard Worker     }
465*e1997b9aSAndroid Build Coastguard Worker     return iter->second;
466*e1997b9aSAndroid Build Coastguard Worker }
467*e1997b9aSAndroid Build Coastguard Worker 
deleteCredential()468*e1997b9aSAndroid Build Coastguard Worker bool CredentialData::deleteCredential() {
469*e1997b9aSAndroid Build Coastguard Worker     if (unlink(fileName_.c_str()) != 0) {
470*e1997b9aSAndroid Build Coastguard Worker         PLOG(ERROR) << "Error deleting " << fileName_;
471*e1997b9aSAndroid Build Coastguard Worker         return false;
472*e1997b9aSAndroid Build Coastguard Worker     }
473*e1997b9aSAndroid Build Coastguard Worker     return true;
474*e1997b9aSAndroid Build Coastguard Worker }
475*e1997b9aSAndroid Build Coastguard Worker 
credentialExists(const string & dataPath,uid_t ownerUid,const string & name)476*e1997b9aSAndroid Build Coastguard Worker optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ownerUid,
477*e1997b9aSAndroid Build Coastguard Worker                                                 const string& name) {
478*e1997b9aSAndroid Build Coastguard Worker     struct stat statbuf;
479*e1997b9aSAndroid Build Coastguard Worker     string filename = calculateCredentialFileName(dataPath, ownerUid, name);
480*e1997b9aSAndroid Build Coastguard Worker     if (stat(filename.c_str(), &statbuf) != 0) {
481*e1997b9aSAndroid Build Coastguard Worker         if (errno == ENOENT) {
482*e1997b9aSAndroid Build Coastguard Worker             return false;
483*e1997b9aSAndroid Build Coastguard Worker         }
484*e1997b9aSAndroid Build Coastguard Worker         PLOG(ERROR) << "Error getting information about " << filename;
485*e1997b9aSAndroid Build Coastguard Worker         return {};
486*e1997b9aSAndroid Build Coastguard Worker     }
487*e1997b9aSAndroid Build Coastguard Worker     return true;
488*e1997b9aSAndroid Build Coastguard Worker }
489*e1997b9aSAndroid Build Coastguard Worker 
490*e1997b9aSAndroid Build Coastguard Worker // ---
491*e1997b9aSAndroid Build Coastguard Worker 
setAvailableAuthenticationKeys(int keyCount,int maxUsesPerKey,int64_t minValidTimeMillis)492*e1997b9aSAndroid Build Coastguard Worker void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
493*e1997b9aSAndroid Build Coastguard Worker                                                     int64_t minValidTimeMillis) {
494*e1997b9aSAndroid Build Coastguard Worker     keyCount_ = keyCount;
495*e1997b9aSAndroid Build Coastguard Worker     maxUsesPerKey_ = maxUsesPerKey;
496*e1997b9aSAndroid Build Coastguard Worker     minValidTimeMillis_ = minValidTimeMillis;
497*e1997b9aSAndroid Build Coastguard Worker 
498*e1997b9aSAndroid Build Coastguard Worker     // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
499*e1997b9aSAndroid Build Coastguard Worker     // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
500*e1997b9aSAndroid Build Coastguard Worker     // and |pendingCertificate| fields. Those will be filled out when the
501*e1997b9aSAndroid Build Coastguard Worker     // getAuthKeysNeedingCertification() is called.
502*e1997b9aSAndroid Build Coastguard Worker     //
503*e1997b9aSAndroid Build Coastguard Worker     // If shrinking, we'll just delete the AuthKeyData structs at the end. There's nothing
504*e1997b9aSAndroid Build Coastguard Worker     // else to do, the HAL doesn't need to know we're nuking these authentication keys.
505*e1997b9aSAndroid Build Coastguard Worker     //
506*e1997b9aSAndroid Build Coastguard Worker     // Therefore, in either case it's as simple as just resizing the vector.
507*e1997b9aSAndroid Build Coastguard Worker     authKeyDatas_.resize(keyCount_);
508*e1997b9aSAndroid Build Coastguard Worker }
509*e1997b9aSAndroid Build Coastguard Worker 
getAuthKeyDatas() const510*e1997b9aSAndroid Build Coastguard Worker const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
511*e1997b9aSAndroid Build Coastguard Worker     return authKeyDatas_;
512*e1997b9aSAndroid Build Coastguard Worker }
513*e1997b9aSAndroid Build Coastguard Worker 
514*e1997b9aSAndroid Build Coastguard Worker tuple<int /* keyCount */, int /*maxUsersPerKey */, int64_t /* minValidTimeMillis */>
getAvailableAuthenticationKeys() const515*e1997b9aSAndroid Build Coastguard Worker CredentialData::getAvailableAuthenticationKeys() const {
516*e1997b9aSAndroid Build Coastguard Worker     return std::make_tuple(keyCount_, maxUsesPerKey_, minValidTimeMillis_);
517*e1997b9aSAndroid Build Coastguard Worker }
518*e1997b9aSAndroid Build Coastguard Worker 
findAuthKey_(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys)519*e1997b9aSAndroid Build Coastguard Worker AuthKeyData* CredentialData::findAuthKey_(bool allowUsingExhaustedKeys,
520*e1997b9aSAndroid Build Coastguard Worker                                           bool allowUsingExpiredKeys) {
521*e1997b9aSAndroid Build Coastguard Worker     AuthKeyData* candidate = nullptr;
522*e1997b9aSAndroid Build Coastguard Worker 
523*e1997b9aSAndroid Build Coastguard Worker     time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
524*e1997b9aSAndroid Build Coastguard Worker     int64_t nowMilliSeconds;
525*e1997b9aSAndroid Build Coastguard Worker     if (__builtin_mul_overflow(int64_t(now), int64_t(1000), &nowMilliSeconds)) {
526*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Overflow converting " << now << " to milliseconds";
527*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
528*e1997b9aSAndroid Build Coastguard Worker     }
529*e1997b9aSAndroid Build Coastguard Worker 
530*e1997b9aSAndroid Build Coastguard Worker     for (AuthKeyData& data : authKeyDatas_) {
531*e1997b9aSAndroid Build Coastguard Worker         if (nowMilliSeconds > data.expirationDateMillisSinceEpoch) {
532*e1997b9aSAndroid Build Coastguard Worker             if (!allowUsingExpiredKeys) {
533*e1997b9aSAndroid Build Coastguard Worker                 continue;
534*e1997b9aSAndroid Build Coastguard Worker             }
535*e1997b9aSAndroid Build Coastguard Worker         }
536*e1997b9aSAndroid Build Coastguard Worker         if (data.certificate.size() != 0) {
537*e1997b9aSAndroid Build Coastguard Worker             // Not expired, include in normal check
538*e1997b9aSAndroid Build Coastguard Worker             if (candidate == nullptr || data.useCount < candidate->useCount) {
539*e1997b9aSAndroid Build Coastguard Worker                 candidate = &data;
540*e1997b9aSAndroid Build Coastguard Worker             }
541*e1997b9aSAndroid Build Coastguard Worker         }
542*e1997b9aSAndroid Build Coastguard Worker     }
543*e1997b9aSAndroid Build Coastguard Worker 
544*e1997b9aSAndroid Build Coastguard Worker     if (candidate == nullptr) {
545*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
546*e1997b9aSAndroid Build Coastguard Worker     }
547*e1997b9aSAndroid Build Coastguard Worker 
548*e1997b9aSAndroid Build Coastguard Worker     if (candidate->useCount >= maxUsesPerKey_ && !allowUsingExhaustedKeys) {
549*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
550*e1997b9aSAndroid Build Coastguard Worker     }
551*e1997b9aSAndroid Build Coastguard Worker 
552*e1997b9aSAndroid Build Coastguard Worker     return candidate;
553*e1997b9aSAndroid Build Coastguard Worker }
554*e1997b9aSAndroid Build Coastguard Worker 
selectAuthKey(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys,bool incrementUsageCount)555*e1997b9aSAndroid Build Coastguard Worker const AuthKeyData* CredentialData::selectAuthKey(bool allowUsingExhaustedKeys,
556*e1997b9aSAndroid Build Coastguard Worker                                                  bool allowUsingExpiredKeys,
557*e1997b9aSAndroid Build Coastguard Worker                                                  bool incrementUsageCount) {
558*e1997b9aSAndroid Build Coastguard Worker     AuthKeyData* candidate;
559*e1997b9aSAndroid Build Coastguard Worker 
560*e1997b9aSAndroid Build Coastguard Worker     // First try to find a un-expired key..
561*e1997b9aSAndroid Build Coastguard Worker     candidate = findAuthKey_(allowUsingExhaustedKeys, false);
562*e1997b9aSAndroid Build Coastguard Worker     if (candidate == nullptr) {
563*e1997b9aSAndroid Build Coastguard Worker         // That didn't work, there are no un-expired keys and we don't allow using expired keys.
564*e1997b9aSAndroid Build Coastguard Worker         if (!allowUsingExpiredKeys) {
565*e1997b9aSAndroid Build Coastguard Worker             return nullptr;
566*e1997b9aSAndroid Build Coastguard Worker         }
567*e1997b9aSAndroid Build Coastguard Worker 
568*e1997b9aSAndroid Build Coastguard Worker         // See if there's an expired key then...
569*e1997b9aSAndroid Build Coastguard Worker         candidate = findAuthKey_(allowUsingExhaustedKeys, true);
570*e1997b9aSAndroid Build Coastguard Worker         if (candidate == nullptr) {
571*e1997b9aSAndroid Build Coastguard Worker             return nullptr;
572*e1997b9aSAndroid Build Coastguard Worker         }
573*e1997b9aSAndroid Build Coastguard Worker     }
574*e1997b9aSAndroid Build Coastguard Worker 
575*e1997b9aSAndroid Build Coastguard Worker     if (incrementUsageCount) {
576*e1997b9aSAndroid Build Coastguard Worker         candidate->useCount += 1;
577*e1997b9aSAndroid Build Coastguard Worker     }
578*e1997b9aSAndroid Build Coastguard Worker     return candidate;
579*e1997b9aSAndroid Build Coastguard Worker }
580*e1997b9aSAndroid Build Coastguard Worker 
581*e1997b9aSAndroid Build Coastguard Worker optional<vector<vector<uint8_t>>>
getAuthKeysNeedingCertification(const sp<IIdentityCredential> & halBinder)582*e1997b9aSAndroid Build Coastguard Worker CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder) {
583*e1997b9aSAndroid Build Coastguard Worker 
584*e1997b9aSAndroid Build Coastguard Worker     vector<vector<uint8_t>> keysNeedingCert;
585*e1997b9aSAndroid Build Coastguard Worker 
586*e1997b9aSAndroid Build Coastguard Worker     time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
587*e1997b9aSAndroid Build Coastguard Worker     int64_t nowMilliseconds;
588*e1997b9aSAndroid Build Coastguard Worker     if (__builtin_mul_overflow(int64_t(now), int64_t(1000), &nowMilliseconds)) {
589*e1997b9aSAndroid Build Coastguard Worker         LOG(ERROR) << "Overflow converting " << now << " to milliseconds";
590*e1997b9aSAndroid Build Coastguard Worker         return {};
591*e1997b9aSAndroid Build Coastguard Worker     }
592*e1997b9aSAndroid Build Coastguard Worker 
593*e1997b9aSAndroid Build Coastguard Worker     for (AuthKeyData& data : authKeyDatas_) {
594*e1997b9aSAndroid Build Coastguard Worker         bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
595*e1997b9aSAndroid Build Coastguard Worker         int64_t expirationDateAdjusted = data.expirationDateMillisSinceEpoch - minValidTimeMillis_;
596*e1997b9aSAndroid Build Coastguard Worker         bool keyBeyondAdjustedExpirationDate = (nowMilliseconds > expirationDateAdjusted);
597*e1997b9aSAndroid Build Coastguard Worker         bool newKeyNeeded =
598*e1997b9aSAndroid Build Coastguard Worker             (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondAdjustedExpirationDate;
599*e1997b9aSAndroid Build Coastguard Worker         bool certificationPending = (data.pendingCertificate.size() > 0);
600*e1997b9aSAndroid Build Coastguard Worker         if (newKeyNeeded && !certificationPending) {
601*e1997b9aSAndroid Build Coastguard Worker             vector<uint8_t> signingKeyBlob;
602*e1997b9aSAndroid Build Coastguard Worker             Certificate signingKeyCertificate;
603*e1997b9aSAndroid Build Coastguard Worker             if (!halBinder->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate)
604*e1997b9aSAndroid Build Coastguard Worker                      .isOk()) {
605*e1997b9aSAndroid Build Coastguard Worker                 LOG(ERROR) << "Error generating signing key-pair";
606*e1997b9aSAndroid Build Coastguard Worker                 return {};
607*e1997b9aSAndroid Build Coastguard Worker             }
608*e1997b9aSAndroid Build Coastguard Worker             data.pendingCertificate = signingKeyCertificate.encodedCertificate;
609*e1997b9aSAndroid Build Coastguard Worker             data.pendingKeyBlob = signingKeyBlob;
610*e1997b9aSAndroid Build Coastguard Worker             certificationPending = true;
611*e1997b9aSAndroid Build Coastguard Worker         }
612*e1997b9aSAndroid Build Coastguard Worker 
613*e1997b9aSAndroid Build Coastguard Worker         if (certificationPending) {
614*e1997b9aSAndroid Build Coastguard Worker             keysNeedingCert.push_back(data.pendingCertificate);
615*e1997b9aSAndroid Build Coastguard Worker         }
616*e1997b9aSAndroid Build Coastguard Worker     }
617*e1997b9aSAndroid Build Coastguard Worker     return keysNeedingCert;
618*e1997b9aSAndroid Build Coastguard Worker }
619*e1997b9aSAndroid Build Coastguard Worker 
storeStaticAuthenticationData(const vector<uint8_t> & authenticationKey,int64_t expirationDateMillisSinceEpoch,const vector<uint8_t> & staticAuthData)620*e1997b9aSAndroid Build Coastguard Worker bool CredentialData::storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
621*e1997b9aSAndroid Build Coastguard Worker                                                    int64_t expirationDateMillisSinceEpoch,
622*e1997b9aSAndroid Build Coastguard Worker                                                    const vector<uint8_t>& staticAuthData) {
623*e1997b9aSAndroid Build Coastguard Worker     for (AuthKeyData& data : authKeyDatas_) {
624*e1997b9aSAndroid Build Coastguard Worker         if (data.pendingCertificate == authenticationKey) {
625*e1997b9aSAndroid Build Coastguard Worker             data.certificate = data.pendingCertificate;
626*e1997b9aSAndroid Build Coastguard Worker             data.keyBlob = data.pendingKeyBlob;
627*e1997b9aSAndroid Build Coastguard Worker             data.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
628*e1997b9aSAndroid Build Coastguard Worker             data.staticAuthenticationData = staticAuthData;
629*e1997b9aSAndroid Build Coastguard Worker             data.pendingCertificate.clear();
630*e1997b9aSAndroid Build Coastguard Worker             data.pendingKeyBlob.clear();
631*e1997b9aSAndroid Build Coastguard Worker             data.useCount = 0;
632*e1997b9aSAndroid Build Coastguard Worker             return true;
633*e1997b9aSAndroid Build Coastguard Worker         }
634*e1997b9aSAndroid Build Coastguard Worker     }
635*e1997b9aSAndroid Build Coastguard Worker     return false;
636*e1997b9aSAndroid Build Coastguard Worker }
637*e1997b9aSAndroid Build Coastguard Worker 
638*e1997b9aSAndroid Build Coastguard Worker }  // namespace identity
639*e1997b9aSAndroid Build Coastguard Worker }  // namespace security
640*e1997b9aSAndroid Build Coastguard Worker }  // namespace android
641