blob: f58ec166315fa6ca2bd5ee1b083058ba587e4a5d [file] [log] [blame]
David Zeuthenab3e5652019-10-28 13:32:48 -04001/*
2 * Copyright (c) 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "WritableCredential"
18
19#include <android-base/logging.h>
20
21#include <android/hardware/identity/support/IdentityCredentialSupport.h>
22
23#include <android/security/identity/ICredentialStore.h>
24
25#include <binder/IPCThreadState.h>
26
27#include <cppbor.h>
28#include <cppbor_parse.h>
29
30#include "CredentialData.h"
31#include "Util.h"
32#include "WritableCredential.h"
33
34namespace android {
35namespace security {
36namespace identity {
37
38using ::std::pair;
39
40using ::android::hardware::hidl_vec;
41
42using ::android::hardware::identity::V1_0::Result;
43using ::android::hardware::identity::V1_0::ResultCode;
44using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
45
46using ::android::hardware::identity::support::chunkVector;
47
48WritableCredential::WritableCredential(const string& dataPath, const string& credentialName,
49 const string& /*docType*/, size_t dataChunkSize,
50 sp<IWritableIdentityCredential> halBinder)
51 : dataPath_(dataPath), credentialName_(credentialName), dataChunkSize_(dataChunkSize),
52 halBinder_(halBinder) {}
53
54WritableCredential::~WritableCredential() {}
55
56Status WritableCredential::ensureAttestationCertificateExists(const vector<uint8_t>& challenge) {
57 vector<uint8_t> attestationCertificate;
58
59 if (!attestationCertificate_.empty()) {
60 return Status::ok();
61 }
62
63 Result result;
64 halBinder_->getAttestationCertificate(
65 challenge, [&](const Result& _result, const hidl_vec<uint8_t>& _attestationCertificate) {
66 result = _result;
67 attestationCertificate = _attestationCertificate;
68 });
69 if (result.code != ResultCode::OK) {
70 LOG(ERROR) << "Error calling getAttestationCertificate()";
71 return halResultToGenericError(result);
72 }
73 attestationCertificate_ = attestationCertificate;
74 return Status::ok();
75}
76
77Status WritableCredential::getCredentialKeyCertificateChain(const vector<uint8_t>& challenge,
78 vector<uint8_t>* _aidl_return) {
79
80 Status ensureStatus = ensureAttestationCertificateExists(challenge);
81 if (!ensureStatus.isOk()) {
82 return ensureStatus;
83 }
84
85 *_aidl_return = attestationCertificate_;
86 return Status::ok();
87}
88
89Status
90WritableCredential::personalize(const vector<AccessControlProfileParcel>& accessControlProfiles,
91 const vector<EntryNamespaceParcel>& entryNamespaces,
92 int64_t secureUserId, vector<uint8_t>* _aidl_return) {
93 Status ensureStatus = ensureAttestationCertificateExists({});
94 if (!ensureStatus.isOk()) {
95 return ensureStatus;
96 }
97
98 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
99 CredentialData data = CredentialData(dataPath_, callingUid, credentialName_);
100
101 // Note: The value 0 is used to convey that no user-authentication is needed for this
102 // credential. This is to allow creating credentials w/o user authentication on devices
103 // where Secure lock screen is not enabled.
104 data.setSecureUserId(secureUserId);
105
106 data.setAttestationCertificate(attestationCertificate_);
107
108 vector<uint16_t> entryCounts;
109 for (const EntryNamespaceParcel& ensParcel : entryNamespaces) {
110 entryCounts.push_back(ensParcel.entries.size());
111 }
112
113 Result result;
114 halBinder_->startPersonalization(accessControlProfiles.size(), entryCounts,
115 [&](const Result& _result) { result = _result; });
116 if (result.code != ResultCode::OK) {
117 return halResultToGenericError(result);
118 }
119
120 for (const AccessControlProfileParcel& acpParcel : accessControlProfiles) {
121 halBinder_->addAccessControlProfile(
122 acpParcel.id, acpParcel.readerCertificate, acpParcel.userAuthenticationRequired,
123 acpParcel.userAuthenticationTimeoutMillis, secureUserId,
124 [&](const Result& _result, const SecureAccessControlProfile& profile) {
125 data.addSecureAccessControlProfile(profile);
126 result = _result;
127 });
128 if (result.code != ResultCode::OK) {
129 return halResultToGenericError(result);
130 }
131 }
132
133 for (const EntryNamespaceParcel& ensParcel : entryNamespaces) {
134 for (const EntryParcel& eParcel : ensParcel.entries) {
135 vector<vector<uint8_t>> chunks = chunkVector(eParcel.value, dataChunkSize_);
136
137 vector<uint16_t> ids;
138 std::copy(eParcel.accessControlProfileIds.begin(),
139 eParcel.accessControlProfileIds.end(), std::back_inserter(ids));
140
141 halBinder_->beginAddEntry(ids, ensParcel.namespaceName, eParcel.name,
142 eParcel.value.size(),
143 [&](const Result& _result) { result = _result; });
144 if (result.code != ResultCode::OK) {
145 return halResultToGenericError(result);
146 }
147
148 vector<vector<uint8_t>> encryptedChunks;
149 for (const auto& chunk : chunks) {
150 halBinder_->addEntryValue(
151 chunk, [&](const Result& _result, const hidl_vec<uint8_t>& encryptedContent) {
152 result = _result;
153 encryptedChunks.push_back(encryptedContent);
154 });
155 if (result.code != ResultCode::OK) {
156 return halResultToGenericError(result);
157 }
158 }
159 EntryData eData;
160 eData.size = eParcel.value.size();
161 eData.accessControlProfileIds = std::move(ids);
162 eData.encryptedChunks = std::move(encryptedChunks);
163 data.addEntryData(ensParcel.namespaceName, eParcel.name, eData);
164 }
165 }
166
167 vector<uint8_t> credentialData;
168 vector<uint8_t> proofOfProvisioningSignature;
169 halBinder_->finishAddingEntries([&](const Result& _result,
170 const hidl_vec<uint8_t>& _credentialData,
171 const hidl_vec<uint8_t>& _proofOfProvisioningSignature) {
172 data.setCredentialData(_credentialData);
173 result = _result;
174 credentialData = _credentialData;
175 proofOfProvisioningSignature = _proofOfProvisioningSignature;
176 });
177 if (result.code != ResultCode::OK) {
178 return halResultToGenericError(result);
179 }
180
181 if (!data.saveToDisk()) {
182 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
183 "Error saving credential data to disk");
184 }
185
186 *_aidl_return = proofOfProvisioningSignature;
187 return Status::ok();
188}
189
190} // namespace identity
191} // namespace security
192} // namespace android