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