OSDN Git Service

Fix inverted error code.
[android-x86/system-hardware-interfaces.git] / wifi / keystore / 1.0 / default / keystore.cpp
1 #include <android-base/logging.h>
2 #include <android/security/keystore/BnKeystoreOperationResultCallback.h>
3 #include <android/security/keystore/BnKeystoreResponseCallback.h>
4 #include <android/security/keystore/IKeystoreService.h>
5 #include <binder/IServiceManager.h>
6 #include <private/android_filesystem_config.h>
7
8 #include <keystore/KeyCharacteristics.h>
9 #include <keystore/KeymasterArguments.h>
10 #include <keystore/KeymasterBlob.h>
11 #include <keystore/KeystoreResponse.h>
12 #include <keystore/OperationResult.h>
13 #include <keystore/keymaster_types.h>
14 #include <keystore/keystore.h>
15 #include <keystore/keystore_hidl_support.h>
16 #include <keystore/keystore_promises.h>
17 #include <keystore/keystore_return_types.h>
18
19 #include <future>
20 #include <vector>
21 #include "include/wifikeystorehal/keystore.h"
22
23 using android::hardware::keymaster::V4_0::Algorithm;
24 using android::hardware::keymaster::V4_0::authorizationValue;
25 using android::hardware::keymaster::V4_0::Digest;
26 using android::hardware::keymaster::V4_0::KeyFormat;
27 using android::hardware::keymaster::V4_0::KeyParameter;
28 using android::hardware::keymaster::V4_0::KeyPurpose;
29 using android::hardware::keymaster::V4_0::NullOr;
30 using android::hardware::keymaster::V4_0::PaddingMode;
31 using android::hardware::keymaster::V4_0::TAG_ALGORITHM;
32 using android::hardware::keymaster::V4_0::TAG_DIGEST;
33 using android::hardware::keymaster::V4_0::TAG_PADDING;
34 using android::security::keymaster::ExportResult;
35 using android::security::keymaster::KeyCharacteristics;
36 using android::security::keymaster::KeymasterArguments;
37 using android::security::keymaster::KeymasterBlob;
38 using android::security::keymaster::OperationResult;
39
40 using KSReturn = keystore::KeyStoreNativeReturnCode;
41
42 namespace {
43 constexpr const char kKeystoreServiceName[] = "android.security.keystore";
44 constexpr int32_t UID_SELF = -1;
45
46 using keystore::KeyCharacteristicsPromise;
47 using keystore::KeystoreExportPromise;
48 using keystore::KeystoreResponsePromise;
49 using keystore::OperationResultPromise;
50
51 };  // namespace
52
53 #define AT __func__ << ":" << __LINE__ << " "
54
55 namespace android {
56 namespace system {
57 namespace wifi {
58 namespace keystore {
59 namespace V1_0 {
60 namespace implementation {
61
62 using security::keystore::IKeystoreService;
63 // Methods from ::android::hardware::wifi::keystore::V1_0::IKeystore follow.
64 Return<void> Keystore::getBlob(const hidl_string& key, getBlob_cb _hidl_cb) {
65     sp<IKeystoreService> service = interface_cast<IKeystoreService>(
66         defaultServiceManager()->getService(String16(kKeystoreServiceName)));
67     if (service == nullptr) {
68         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
69         return Void();
70     }
71     ::std::vector<uint8_t> value;
72     // Retrieve the blob as wifi user.
73     auto ret = service->get(String16(key.c_str()), AID_WIFI, &value);
74     if (!ret.isOk()) {
75         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
76         return Void();
77     }
78     _hidl_cb(KeystoreStatusCode::SUCCESS, (hidl_vec<uint8_t>)value);
79     return Void();
80 }
81
82 Return<void> Keystore::getPublicKey(const hidl_string& keyId, getPublicKey_cb _hidl_cb) {
83     sp<IServiceManager> sm = defaultServiceManager();
84     sp<IBinder> binder = sm->getService(String16(kKeystoreServiceName));
85     sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
86
87     if (service == nullptr) {
88         LOG(ERROR) << AT << "could not contact keystore";
89         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
90         return Void();
91     }
92
93     int32_t error_code;
94     android::sp<KeystoreExportPromise> promise(new KeystoreExportPromise);
95     auto future = promise->get_future();
96     auto binder_result = service->exportKey(
97         promise, String16(keyId.c_str()), static_cast<int32_t>(KeyFormat::X509),
98         KeymasterBlob() /* clientId */, KeymasterBlob() /* appData */, UID_SELF, &error_code);
99     if (!binder_result.isOk()) {
100         LOG(ERROR) << AT << "communication error while calling keystore";
101         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
102         return Void();
103     }
104
105     KSReturn rc(error_code);
106     if (!rc.isOk()) {
107         LOG(ERROR) << AT << "exportKey failed: " << error_code;
108         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
109         return Void();
110     }
111
112     auto export_result = future.get();
113     if (!export_result.resultCode.isOk()) {
114         LOG(ERROR) << AT << "exportKey failed: " << export_result.resultCode;
115         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
116         return Void();
117     }
118
119     _hidl_cb(KeystoreStatusCode::SUCCESS, export_result.exportData);
120     return Void();
121 }
122
123 static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
124     const ::android::security::keymaster::KeyCharacteristics& characteristics) {
125     for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
126         auto algo = authorizationValue(TAG_ALGORITHM, param);
127         if (algo.isOk()) return algo;
128     }
129     for (const auto& param : characteristics.softwareEnforced.getParameters()) {
130         auto algo = authorizationValue(TAG_ALGORITHM, param);
131         if (algo.isOk()) return algo;
132     }
133     return {};
134 }
135
136 Return<void> Keystore::sign(const hidl_string& keyId, const hidl_vec<uint8_t>& dataToSign,
137                             sign_cb _hidl_cb) {
138     sp<IServiceManager> sm = defaultServiceManager();
139     sp<IBinder> binder = sm->getService(String16(kKeystoreServiceName));
140     sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
141
142     if (service == nullptr) {
143         LOG(ERROR) << AT << "could not contact keystore";
144         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
145         return Void();
146     }
147
148     String16 key_name16(keyId.c_str());
149     int32_t error_code;
150     android::sp<KeyCharacteristicsPromise> kc_promise(new KeyCharacteristicsPromise);
151     auto kc_future = kc_promise->get_future();
152     auto binder_result = service->getKeyCharacteristics(kc_promise, key_name16, KeymasterBlob(),
153                                                         KeymasterBlob(), UID_SELF, &error_code);
154     if (!binder_result.isOk()) {
155         LOG(ERROR) << AT << "communication error while calling keystore";
156         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
157         return Void();
158     }
159     KSReturn rc(error_code);
160     if (!rc.isOk()) {
161         LOG(ERROR) << AT << "getKeyCharacteristics failed: " << error_code;
162         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
163         return Void();
164     }
165
166     auto [km_response, characteristics] = kc_future.get();
167
168     if (!KSReturn(km_response.response_code()).isOk()) {
169         LOG(ERROR) << AT << "getKeyCharacteristics failed: " << km_response.response_code();
170         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
171         return Void();
172     }
173
174     auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
175     if (!algorithm.isOk()) {
176         LOG(ERROR) << AT << "could not get algorithm from key characteristics";
177         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
178         return Void();
179     }
180
181     hidl_vec<KeyParameter> params(3);
182     params[0] = Authorization(TAG_DIGEST, Digest::NONE);
183     params[1] = Authorization(TAG_PADDING, PaddingMode::NONE);
184     params[2] = Authorization(TAG_ALGORITHM, algorithm.value());
185
186     android::sp<android::IBinder> token(new android::BBinder);
187     sp<OperationResultPromise> promise(new OperationResultPromise());
188     auto future = promise->get_future();
189     binder_result = service->begin(promise, token, key_name16, (int)KeyPurpose::SIGN,
190                                    true /*pruneable*/, KeymasterArguments(params),
191                                    std::vector<uint8_t>() /* entropy */, UID_SELF, &error_code);
192     if (!binder_result.isOk()) {
193         LOG(ERROR) << AT << "communication error while calling keystore";
194         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
195         return Void();
196     }
197
198     rc = KSReturn(error_code);
199     if (!rc.isOk()) {
200         LOG(ERROR) << AT << "Keystore begin returned: " << rc;
201         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
202         return Void();
203     }
204
205     OperationResult result = future.get();
206     if (!result.resultCode.isOk()) {
207         LOG(ERROR) << AT << "begin failed: " << result.resultCode;
208         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
209         return Void();
210     }
211     auto handle = std::move(result.token);
212
213     const uint8_t* in = dataToSign.data();
214     size_t len = dataToSign.size();
215     do {
216         future = {};
217         binder_result = service->update(promise, handle, KeymasterArguments(params),
218                                         std::vector<uint8_t>(in, in + len), &error_code);
219         if (!binder_result.isOk()) {
220             LOG(ERROR) << AT << "communication error while calling keystore";
221             _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
222             return Void();
223         }
224
225         rc = KSReturn(error_code);
226         if (!rc.isOk()) {
227             LOG(ERROR) << AT << "Keystore update returned: " << rc;
228             _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
229             return Void();
230         }
231
232         result = future.get();
233
234         if (!result.resultCode.isOk()) {
235             LOG(ERROR) << AT << "update failed: " << result.resultCode;
236             _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
237             return Void();
238         }
239         if ((size_t)result.inputConsumed > len) {
240             LOG(ERROR) << AT << "update consumed more data than provided";
241             sp<KeystoreResponsePromise> abortPromise(new KeystoreResponsePromise);
242             auto abortFuture = abortPromise->get_future();
243             binder_result = service->abort(abortPromise, handle, &error_code);
244             if (!binder_result.isOk()) {
245                 LOG(ERROR) << AT << "communication error while calling keystore";
246                 _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
247                 return Void();
248             }
249             // This is mainly for logging since we already failed.
250             // But if abort returned OK we have to wait untill abort calls the callback
251             // hence the call to abortFuture.get().
252             if (!KSReturn(error_code).isOk()) {
253                 LOG(ERROR) << AT << "abort failed: " << error_code;
254             } else if (!(rc = KSReturn(abortFuture.get().response_code())).isOk()) {
255                 LOG(ERROR) << AT << "abort failed: " << rc;
256             }
257             _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
258             return Void();
259         }
260         len -= result.inputConsumed;
261         in += result.inputConsumed;
262     } while (len > 0);
263
264     future = {};
265     promise = new OperationResultPromise();
266     future = promise->get_future();
267
268     binder_result = service->finish(promise, handle, KeymasterArguments(params),
269                                     std::vector<uint8_t>() /* signature */,
270                                     std::vector<uint8_t>() /* entropy */, &error_code);
271     if (!binder_result.isOk()) {
272         LOG(ERROR) << AT << "communication error while calling keystore";
273         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
274         return Void();
275     }
276
277     rc = KSReturn(error_code);
278     if (!rc.isOk()) {
279         LOG(ERROR) << AT << "Keystore finish returned: " << rc;
280         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
281         return Void();
282     }
283
284     result = future.get();
285
286     if (!result.resultCode.isOk()) {
287         LOG(ERROR) << AT << "finish failed: " << result.resultCode;
288         _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {});
289         return Void();
290     }
291
292     _hidl_cb(KeystoreStatusCode::SUCCESS, result.data);
293     return Void();
294 }
295
296 IKeystore* HIDL_FETCH_IKeystore(const char* /* name */) {
297     return new Keystore();
298 }
299 }  // namespace implementation
300 }  // namespace V1_0
301 }  // namespace keystore
302 }  // namespace wifi
303 }  // namespace system
304 }  // namespace android