blob: b13a7b08f64f15dfd67fc820a8fffaa3afb84e13 [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 "CredentialStore"
18
19#include <algorithm>
20
21#include <android-base/logging.h>
22
23#include <binder/IPCThreadState.h>
24
25#include "Credential.h"
26#include "CredentialStore.h"
27#include "Util.h"
28#include "WritableCredential.h"
29
30namespace android {
31namespace security {
32namespace identity {
33
34using ::android::hardware::hidl_string;
35using ::android::hardware::hidl_vec;
36using ::android::hardware::identity::V1_0::Result;
37using ::android::hardware::identity::V1_0::ResultCode;
38
39using ::android::hardware::identity::V1_0::IWritableIdentityCredential;
40
41CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
42 : dataPath_(dataPath), hal_(hal) {}
43
44bool CredentialStore::init() {
45 Result result;
46 hal_->getHardwareInformation([&](const Result& _result, const hidl_string& credentialStoreName,
47 const hidl_string& credentialStoreAuthorName,
48 uint32_t _dataChunkSize, bool _isDirectAccess,
49 const hidl_vec<hidl_string>& _supportedDocTypes) {
50 result = _result;
51 dataChunkSize_ = _dataChunkSize;
52 isDirectAccess_ = _isDirectAccess;
53 supportedDocTypes_.clear();
54 for (auto& docType : _supportedDocTypes) {
55 supportedDocTypes_.push_back(docType);
56 }
57 LOG(INFO) << "Connected to Identity Credential HAL with name '" << credentialStoreName
58 << "' authored by '" << credentialStoreAuthorName << "' with chunk size "
59 << _dataChunkSize << " and directoAccess set to "
60 << (_isDirectAccess ? "true" : "false");
61 });
62 if (result.code != ResultCode::OK) {
63 LOG(ERROR) << "Error getting hardware information: " << (int)result.code << ": "
64 << result.message;
65 return false;
66 }
67 return true;
68}
69
70CredentialStore::~CredentialStore() {}
71
72Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
73 SecurityHardwareInfoParcel info;
74 info.directAccess = isDirectAccess_;
75 info.supportedDocTypes = supportedDocTypes_;
76 *_aidl_return = info;
77 return Status::ok();
78};
79
80Status CredentialStore::createCredential(const std::string& credentialName,
81 const std::string& docType,
82 sp<IWritableCredential>* _aidl_return) {
83 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
84 optional<bool> credentialExists =
85 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
86 if (!credentialExists.has_value()) {
87 return Status::fromServiceSpecificError(
88 ERROR_GENERIC, "Error determining if credential with given name exists");
89 }
90 if (credentialExists.value()) {
91 return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED,
92 "Credential with given name already exists");
93 }
94
95 if (supportedDocTypes_.size() > 0) {
96 if (std::find(supportedDocTypes_.begin(), supportedDocTypes_.end(), docType) ==
97 supportedDocTypes_.end()) {
98 return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
99 "No support for given document type");
100 }
101 }
102
103 Result result;
104 sp<IWritableIdentityCredential> halWritableCredential;
105 hal_->createCredential(
106 docType, false,
107 [&](const Result& _result, const sp<IWritableIdentityCredential>& _halWritableCredential) {
108 result = _result;
109 halWritableCredential = _halWritableCredential;
110 });
111 if (result.code != ResultCode::OK) {
112 return halResultToGenericError(result);
113 }
114
115 sp<IWritableCredential> writableCredential = new WritableCredential(
116 dataPath_, credentialName, docType, dataChunkSize_, halWritableCredential);
117 *_aidl_return = writableCredential;
118 return Status::ok();
119}
120
121// Keep in sync with IdentityCredentialStore.java
122//
123
124const int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1;
125
126Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
127 sp<ICredential>* _aidl_return) {
128 *_aidl_return = nullptr;
129
130 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
131 optional<bool> credentialExists =
132 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
133 if (!credentialExists.has_value()) {
134 return Status::fromServiceSpecificError(
135 ERROR_GENERIC, "Error determining if credential with given name exists");
136 }
137 if (!credentialExists.value()) {
138 return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL,
139 "Credential with given name doesn't exist");
140 }
141
142 // We only support a single cipher-suite right now.
143 if (cipherSuite != CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
144 return Status::fromServiceSpecificError(ERROR_CIPHER_SUITE_NOT_SUPPORTED,
145 "Cipher suite not supported");
146 }
147
148 sp<Credential> credential = new Credential(dataPath_, credentialName);
149
150 Status loadStatus = credential->loadCredential(hal_);
151 if (!loadStatus.isOk()) {
152 LOG(ERROR) << "Error loading credential";
153 } else {
154 *_aidl_return = credential;
155 }
156 return loadStatus;
157}
158
159} // namespace identity
160} // namespace security
161} // namespace android