summaryrefslogtreecommitdiff
path: root/4.0/AmlogicKeymaster4Device.cpp (plain)
blob: 2cf5fb2e633834edf4ae0a01e325b70d6b2f9e1a
1/*
2 **
3 ** Copyright 2018, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#define LOG_TAG "android.hardware.keymaster@4.0-impl.amlogic"
19
20#include <authorization_set.h>
21#include <log/log.h>
22#include <keymaster/android_keymaster_messages.h>
23#include <amlogic_keymaster/AmlogicKeymaster4Device.h>
24#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
25
26using ::keymaster::AbortOperationRequest;
27using ::keymaster::AbortOperationResponse;
28using ::keymaster::AddEntropyRequest;
29using ::keymaster::AddEntropyResponse;
30using ::keymaster::AttestKeyRequest;
31using ::keymaster::AttestKeyResponse;
32using ::keymaster::AuthorizationSet;
33using ::keymaster::BeginOperationRequest;
34using ::keymaster::BeginOperationResponse;
35using ::keymaster::ExportKeyRequest;
36using ::keymaster::ExportKeyResponse;
37using ::keymaster::FinishOperationRequest;
38using ::keymaster::FinishOperationResponse;
39using ::keymaster::GenerateKeyRequest;
40using ::keymaster::GenerateKeyResponse;
41using ::keymaster::GetKeyCharacteristicsRequest;
42using ::keymaster::GetKeyCharacteristicsResponse;
43using ::keymaster::ImportKeyRequest;
44using ::keymaster::ImportKeyResponse;
45using ::keymaster::UpdateOperationRequest;
46using ::keymaster::UpdateOperationResponse;
47using ::keymaster::ng::Tag;
48
49namespace keymaster {
50namespace V4_0 {
51namespace {
52
53inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
54 return keymaster_tag_t(value);
55}
56inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
57 return Tag(value);
58}
59inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
60 return keymaster_purpose_t(value);
61}
62inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
63 return keymaster_key_format_t(value);
64}
65
66inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
67 return static_cast<SecurityLevel>(value);
68}
69
70inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
71 return static_cast<hw_authenticator_type_t>(value);
72}
73
74inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
75 return ErrorCode(value);
76}
77
78inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
79 return keymaster_tag_get_type(tag);
80}
81
82class KmParamSet : public keymaster_key_param_set_t {
83 public:
84 KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
85 params = new keymaster_key_param_t[keyParams.size()];
86 length = keyParams.size();
87 for (size_t i = 0; i < keyParams.size(); ++i) {
88 auto tag = legacy_enum_conversion(keyParams[i].tag);
89 switch (typeFromTag(tag)) {
90 case KM_ENUM:
91 case KM_ENUM_REP:
92 params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
93 break;
94 case KM_UINT:
95 case KM_UINT_REP:
96 params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
97 break;
98 case KM_ULONG:
99 case KM_ULONG_REP:
100 params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
101 break;
102 case KM_DATE:
103 params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
104 break;
105 case KM_BOOL:
106 if (keyParams[i].f.boolValue)
107 params[i] = keymaster_param_bool(tag);
108 else
109 params[i].tag = KM_TAG_INVALID;
110 break;
111 case KM_BIGNUM:
112 case KM_BYTES:
113 params[i] = keymaster_param_blob(tag, &keyParams[i].blob[0],
114 keyParams[i].blob.size());
115 break;
116 case KM_INVALID:
117 default:
118 params[i].tag = KM_TAG_INVALID;
119 /* just skip */
120 break;
121 }
122 }
123 }
124 KmParamSet(KmParamSet&& other) noexcept
125 : keymaster_key_param_set_t{other.params, other.length} {
126 other.length = 0;
127 other.params = nullptr;
128 }
129 KmParamSet(const KmParamSet&) = delete;
130 ~KmParamSet() { delete[] params; }
131};
132
133inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
134 hidl_vec<uint8_t> result;
135 result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
136 return result;
137}
138
139inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
140 hidl_vec<uint8_t> result;
141 result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
142 return result;
143}
144
145inline hidl_vec<uint8_t> kmBuffer2hidlVec(const ::keymaster::Buffer& buf) {
146 hidl_vec<uint8_t> result;
147 result.setToExternal(const_cast<unsigned char*>(buf.peek_read()), buf.available_read());
148 return result;
149}
150
151inline static hidl_vec<hidl_vec<uint8_t>> kmCertChain2Hidl(
152 const keymaster_cert_chain_t& cert_chain) {
153 hidl_vec<hidl_vec<uint8_t>> result;
154 if (!cert_chain.entry_count || !cert_chain.entries) return result;
155
156 result.resize(cert_chain.entry_count);
157 for (size_t i = 0; i < cert_chain.entry_count; ++i) {
158 result[i] = kmBlob2hidlVec(cert_chain.entries[i]);
159 }
160
161 return result;
162}
163
164static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
165 hidl_vec<KeyParameter> result;
166 if (set.length == 0 || set.params == nullptr) return result;
167
168 result.resize(set.length);
169 keymaster_key_param_t* params = set.params;
170 for (size_t i = 0; i < set.length; ++i) {
171 auto tag = params[i].tag;
172 result[i].tag = legacy_enum_conversion(tag);
173 switch (typeFromTag(tag)) {
174 case KM_ENUM:
175 case KM_ENUM_REP:
176 result[i].f.integer = params[i].enumerated;
177 break;
178 case KM_UINT:
179 case KM_UINT_REP:
180 result[i].f.integer = params[i].integer;
181 break;
182 case KM_ULONG:
183 case KM_ULONG_REP:
184 result[i].f.longInteger = params[i].long_integer;
185 break;
186 case KM_DATE:
187 result[i].f.dateTime = params[i].date_time;
188 break;
189 case KM_BOOL:
190 result[i].f.boolValue = params[i].boolean;
191 break;
192 case KM_BIGNUM:
193 case KM_BYTES:
194 result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
195 params[i].blob.data_length);
196 break;
197 case KM_INVALID:
198 default:
199 params[i].tag = KM_TAG_INVALID;
200 /* just skip */
201 break;
202 }
203 }
204 return result;
205}
206
207void addClientAndAppData(const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
208 ::keymaster::AuthorizationSet* params) {
209 params->Clear();
210 if (clientId.size()) {
211 params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
212 }
213 if (appData.size()) {
214 params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
215 }
216}
217
218} // anonymous namespace
219
220AmlogicKeymaster4Device::AmlogicKeymaster4Device(AmlogicKeymaster* impl) : impl_(impl) {}
221
222AmlogicKeymaster4Device::~AmlogicKeymaster4Device() {}
223
224Return<void> AmlogicKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) {
225 _hidl_cb(SecurityLevel::TRUSTED_ENVIRONMENT, "AmlogicKeymaster", "Google");
226 return Void();
227}
228
229Return<void> AmlogicKeymaster4Device::getHmacSharingParameters(
230 getHmacSharingParameters_cb _hidl_cb) {
231 const GetHmacSharingParametersResponse response = impl_->GetHmacSharingParameters();
232 // response.params is not the same as the HIDL structure, we need to convert it
233 V4_0::HmacSharingParameters params;
234 params.seed.setToExternal(const_cast<uint8_t*>(response.params.seed.data),
235 response.params.seed.data_length);
236 static_assert(sizeof(response.params.nonce) == params.nonce.size(), "Nonce sizes don't match");
237 memcpy(params.nonce.data(), response.params.nonce, params.nonce.size());
238 _hidl_cb(legacy_enum_conversion(response.error), params);
239 return Void();
240}
241
242Return<void> AmlogicKeymaster4Device::computeSharedHmac(
243 const hidl_vec<HmacSharingParameters>& params, computeSharedHmac_cb _hidl_cb) {
244 ComputeSharedHmacRequest request;
245 request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
246 request.params_array.num_params = params.size();
247 for (size_t i = 0; i < params.size(); ++i) {
248 request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
249 static_assert(sizeof(request.params_array.params_array[i].nonce) ==
250 decltype(params[i].nonce)::size(),
251 "Nonce sizes don't match");
252 memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
253 params[i].nonce.size());
254 }
255
256 auto response = impl_->ComputeSharedHmac(request);
257 hidl_vec<uint8_t> sharing_check;
258 if (response.error == KM_ERROR_OK) {
259 sharing_check = kmBlob2hidlVec(response.sharing_check);
260 }
261
262 _hidl_cb(legacy_enum_conversion(response.error), sharing_check);
263 return Void();
264}
265
266Return<void> AmlogicKeymaster4Device::verifyAuthorization(
267 uint64_t challenge, const hidl_vec<KeyParameter>& parametersToVerify,
268 const HardwareAuthToken& authToken, verifyAuthorization_cb _hidl_cb) {
269 VerifyAuthorizationRequest request;
270 request.challenge = challenge;
271 request.parameters_to_verify.Reinitialize(KmParamSet(parametersToVerify));
272 request.auth_token.challenge = authToken.challenge;
273 request.auth_token.user_id = authToken.userId;
274 request.auth_token.authenticator_id = authToken.authenticatorId;
275 request.auth_token.authenticator_type = legacy_enum_conversion(authToken.authenticatorType);
276 request.auth_token.timestamp = authToken.timestamp;
277 KeymasterBlob mac(authToken.mac.data(), authToken.mac.size());
278 request.auth_token.mac = mac;
279
280 auto response = impl_->VerifyAuthorization(request);
281
282 ::android::hardware::keymaster::V4_0::VerificationToken token;
283 token.challenge = response.token.challenge;
284 token.timestamp = response.token.timestamp;
285 token.parametersVerified = kmParamSet2Hidl(response.token.parameters_verified);
286 token.securityLevel = legacy_enum_conversion(response.token.security_level);
287 token.mac = kmBlob2hidlVec(response.token.mac);
288
289 _hidl_cb(legacy_enum_conversion(response.error), token);
290
291 return Void();
292}
293
294Return<ErrorCode> AmlogicKeymaster4Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
295 if (data.size() == 0) return ErrorCode::OK;
296 AddEntropyRequest request;
297 request.random_data.Reinitialize(data.data(), data.size());
298
299 AddEntropyResponse response;
300 impl_->AddRngEntropy(request, &response);
301
302 return legacy_enum_conversion(response.error);
303}
304
305Return<void> AmlogicKeymaster4Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
306 generateKey_cb _hidl_cb) {
307 GenerateKeyRequest request;
308 request.key_description.Reinitialize(KmParamSet(keyParams));
309
310 GenerateKeyResponse response;
311 impl_->GenerateKey(request, &response);
312
313 KeyCharacteristics resultCharacteristics;
314 hidl_vec<uint8_t> resultKeyBlob;
315 if (response.error == KM_ERROR_OK) {
316 resultKeyBlob = kmBlob2hidlVec(response.key_blob);
317 resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
318 resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
319 }
320 _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
321 return Void();
322}
323
324Return<void> AmlogicKeymaster4Device::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
325 const hidl_vec<uint8_t>& clientId,
326 const hidl_vec<uint8_t>& appData,
327 getKeyCharacteristics_cb _hidl_cb) {
328 GetKeyCharacteristicsRequest request;
329 request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
330 addClientAndAppData(clientId, appData, &request.additional_params);
331
332 GetKeyCharacteristicsResponse response;
333 impl_->GetKeyCharacteristics(request, &response);
334
335 KeyCharacteristics resultCharacteristics;
336 if (response.error == KM_ERROR_OK) {
337 resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
338 resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
339 }
340 _hidl_cb(legacy_enum_conversion(response.error), resultCharacteristics);
341 return Void();
342}
343
344Return<void> AmlogicKeymaster4Device::importKey(const hidl_vec<KeyParameter>& params,
345 KeyFormat keyFormat,
346 const hidl_vec<uint8_t>& keyData,
347 importKey_cb _hidl_cb) {
348 ImportKeyRequest request;
349 request.key_description.Reinitialize(KmParamSet(params));
350 request.key_format = legacy_enum_conversion(keyFormat);
351 request.SetKeyMaterial(keyData.data(), keyData.size());
352
353 ImportKeyResponse response;
354 impl_->ImportKey(request, &response);
355
356 KeyCharacteristics resultCharacteristics;
357 hidl_vec<uint8_t> resultKeyBlob;
358 if (response.error == KM_ERROR_OK) {
359 resultKeyBlob = kmBlob2hidlVec(response.key_blob);
360 resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
361 resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
362 }
363 _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
364 return Void();
365}
366
367Return<void> AmlogicKeymaster4Device::importWrappedKey(
368 const hidl_vec<uint8_t>& wrappedKeyData, const hidl_vec<uint8_t>& wrappingKeyBlob,
369 const hidl_vec<uint8_t>& maskingKey, const hidl_vec<KeyParameter>& unwrappingParams,
370 uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) {
371 ImportWrappedKeyRequest request;
372 request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
373 request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
374 request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
375 request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
376 request.password_sid = passwordSid;
377 request.biometric_sid = biometricSid;
378
379 ImportWrappedKeyResponse response;
380 impl_->ImportWrappedKey(request, &response);
381
382 KeyCharacteristics resultCharacteristics;
383 hidl_vec<uint8_t> resultKeyBlob;
384 if (response.error == KM_ERROR_OK) {
385 resultKeyBlob = kmBlob2hidlVec(response.key_blob);
386 resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
387 resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
388 }
389 _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
390 return Void();
391}
392
393Return<void> AmlogicKeymaster4Device::exportKey(KeyFormat exportFormat,
394 const hidl_vec<uint8_t>& keyBlob,
395 const hidl_vec<uint8_t>& clientId,
396 const hidl_vec<uint8_t>& appData,
397 exportKey_cb _hidl_cb) {
398 ExportKeyRequest request;
399 request.key_format = legacy_enum_conversion(exportFormat);
400 request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
401 addClientAndAppData(clientId, appData, &request.additional_params);
402
403 ExportKeyResponse response;
404 impl_->ExportKey(request, &response);
405
406 hidl_vec<uint8_t> resultKeyBlob;
407 if (response.error == KM_ERROR_OK) {
408 resultKeyBlob.setToExternal(response.key_data, response.key_data_length);
409 }
410 _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob);
411 return Void();
412}
413
414Return<void> AmlogicKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
415 const hidl_vec<KeyParameter>& attestParams,
416 attestKey_cb _hidl_cb) {
417 AttestKeyRequest request;
418 request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
419 request.attest_params.Reinitialize(KmParamSet(attestParams));
420
421 AttestKeyResponse response;
422 impl_->AttestKey(request, &response);
423
424 hidl_vec<hidl_vec<uint8_t>> resultCertChain;
425 if (response.error == KM_ERROR_OK) {
426 resultCertChain = kmCertChain2Hidl(response.certificate_chain);
427 }
428 _hidl_cb(legacy_enum_conversion(response.error), resultCertChain);
429 return Void();
430}
431
432Return<void> AmlogicKeymaster4Device::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
433 const hidl_vec<KeyParameter>& upgradeParams,
434 upgradeKey_cb _hidl_cb) {
435 UpgradeKeyRequest request;
436 request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
437 request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
438
439 UpgradeKeyResponse response;
440 impl_->UpgradeKey(request, &response);
441
442 if (response.error == KM_ERROR_OK) {
443 _hidl_cb(ErrorCode::OK, kmBlob2hidlVec(response.upgraded_key));
444 } else {
445 _hidl_cb(legacy_enum_conversion(response.error), hidl_vec<uint8_t>());
446 }
447 return Void();
448}
449
450Return<ErrorCode> AmlogicKeymaster4Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
451 DeleteKeyRequest request;
452 request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
453
454 DeleteKeyResponse response;
455 impl_->DeleteKey(request, &response);
456
457 return legacy_enum_conversion(response.error);
458}
459
460Return<ErrorCode> AmlogicKeymaster4Device::deleteAllKeys() {
461 DeleteAllKeysRequest request;
462 DeleteAllKeysResponse response;
463 impl_->DeleteAllKeys(request, &response);
464
465 return legacy_enum_conversion(response.error);
466}
467
468Return<ErrorCode> AmlogicKeymaster4Device::destroyAttestationIds() {
469 return ErrorCode::UNIMPLEMENTED;
470}
471
472Return<void> AmlogicKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
473 const hidl_vec<KeyParameter>& inParams,
474 const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
475 (void)authToken;
476 BeginOperationRequest request;
477 request.purpose = legacy_enum_conversion(purpose);
478 request.SetKeyMaterial(key.data(), key.size());
479 request.additional_params.Reinitialize(KmParamSet(inParams));
480
481 BeginOperationResponse response;
482 impl_->BeginOperation(request, &response);
483
484 hidl_vec<KeyParameter> resultParams;
485 if (response.error == KM_ERROR_OK) {
486 resultParams = kmParamSet2Hidl(response.output_params);
487 }
488
489 _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
490 return Void();
491}
492
493Return<void> AmlogicKeymaster4Device::update(uint64_t operationHandle,
494 const hidl_vec<KeyParameter>& inParams,
495 const hidl_vec<uint8_t>& input,
496 const HardwareAuthToken& authToken,
497 const VerificationToken& verificationToken,
498 update_cb _hidl_cb) {
499 (void)authToken;
500 (void)verificationToken;
501 UpdateOperationRequest request;
502 UpdateOperationResponse response;
503 hidl_vec<KeyParameter> resultParams;
504 hidl_vec<uint8_t> resultBlob;
505 uint32_t resultConsumed = 0;
506
507 request.op_handle = operationHandle;
508 request.additional_params.Reinitialize(KmParamSet(inParams));
509
510 size_t inp_size = input.size();
511 size_t ser_size = request.SerializedSize();
512
513 if (ser_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
514 response.error = KM_ERROR_INVALID_INPUT_LENGTH;
515 } else {
516 if (ser_size + inp_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
517 inp_size = AMLOGIC_KEYMASTER_SEND_BUF_SIZE - ser_size;
518 }
519 request.input.Reinitialize(input.data(), inp_size);
520
521 impl_->UpdateOperation(request, &response);
522
523 if (response.error == KM_ERROR_OK) {
524 resultConsumed = response.input_consumed;
525 resultParams = kmParamSet2Hidl(response.output_params);
526 resultBlob = kmBuffer2hidlVec(response.output);
527 }
528 }
529 _hidl_cb(legacy_enum_conversion(response.error), resultConsumed, resultParams, resultBlob);
530 return Void();
531}
532
533Return<void> AmlogicKeymaster4Device::finish(uint64_t operationHandle,
534 const hidl_vec<KeyParameter>& inParams,
535 const hidl_vec<uint8_t>& input,
536 const hidl_vec<uint8_t>& signature,
537 const HardwareAuthToken& authToken,
538 const VerificationToken& verificationToken,
539 finish_cb _hidl_cb) {
540 (void)authToken;
541 (void)verificationToken;
542 FinishOperationRequest request;
543 request.op_handle = operationHandle;
544 request.input.Reinitialize(input.data(), input.size());
545 request.signature.Reinitialize(signature.data(), signature.size());
546 request.additional_params.Reinitialize(KmParamSet(inParams));
547
548 FinishOperationResponse response;
549 impl_->FinishOperation(request, &response);
550
551 hidl_vec<KeyParameter> resultParams;
552 hidl_vec<uint8_t> resultBlob;
553 if (response.error == KM_ERROR_OK) {
554 resultParams = kmParamSet2Hidl(response.output_params);
555 resultBlob = kmBuffer2hidlVec(response.output);
556 }
557 _hidl_cb(legacy_enum_conversion(response.error), resultParams, resultBlob);
558 return Void();
559}
560
561Return<ErrorCode> AmlogicKeymaster4Device::abort(uint64_t operationHandle) {
562 AbortOperationRequest request;
563 request.op_handle = operationHandle;
564
565 AbortOperationResponse response;
566 impl_->AbortOperation(request, &response);
567
568 return legacy_enum_conversion(response.error);
569}
570} // namespace V4_0
571} // namespace keymaster
572