Adding DropBox logging support for keystore functionality

This will allow us to track the actual usage patterns of keystore
functions and error occurences.

Bug: 36549319
Test: DropBox logging works for keystore tags
Change-Id: Iadfba3afebaa0be753212b1111b68f50b77f9978
(cherry picked from commit d6d8952b34)
This commit is contained in:
Max Bires 2018-02-23 10:53:10 -08:00
parent cf91dcdee3
commit 33aac2dda2
12 changed files with 488 additions and 39 deletions

View file

@ -27,6 +27,8 @@ cc_binary {
"confirmation_manager.cpp",
"entropy.cpp",
"grant_store.cpp",
"key_config.proto",
"key_proto_handler.cpp",
"key_store_service.cpp",
"keyblob_utils.cpp",
"keymaster_enforcement.cpp",
@ -35,6 +37,8 @@ cc_binary {
"keystore_utils.cpp",
"legacy_keymaster_device_wrapper.cpp",
"operation.cpp",
"operation_config.proto",
"operation_proto_handler.cpp",
"permissions.cpp",
"user_state.cpp",
],
@ -57,7 +61,9 @@ cc_binary {
"libkeystore_binder",
"libkeystore_parcelables",
"liblog",
"libprotobuf-cpp-lite",
"libselinux",
"libservices",
"libsoftkeymasterdevice",
"libutils",
"libwifikeystorehal",

View file

@ -66,6 +66,7 @@ using keymaster::TAG_APPLICATION_DATA;
using keymaster::TAG_APPLICATION_ID;
using keymaster::TAG_ATTESTATION_APPLICATION_ID;
using keymaster::TAG_AUTH_TIMEOUT;
using keymaster::TAG_BLOB_USAGE_REQUIREMENTS;
using keymaster::TAG_BLOCK_MODE;
using keymaster::TAG_DIGEST;
using keymaster::TAG_EC_CURVE;
@ -76,6 +77,7 @@ using keymaster::TAG_MIN_MAC_LENGTH;
using keymaster::TAG_MIN_SECONDS_BETWEEN_OPS;
using keymaster::TAG_NO_AUTH_REQUIRED;
using keymaster::TAG_NONCE;
using keymaster::TAG_ORIGIN;
using keymaster::TAG_ORIGINATION_EXPIRE_DATETIME;
using keymaster::TAG_PADDING;
using keymaster::TAG_PURPOSE;

62
keystore/key_config.proto Normal file
View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto2";
package keystore;
option optimize_for = LITE_RUNTIME;
message KeyConfig {
// What type of encryption algorithm is this key being generated/imported for
// e.g. AES, RSA, etc
optional string algorithm = 1;
// Size of the key being generated/imported
optional int32 key_size = 2;
// Log whether the key was generated, imported, securely imported, or derived.
optional string origin = 3;
// What auth types does this key require? If none, then no auth required.
optional string user_auth_type = 4;
// If user authentication is required, is the requirement time based? If it
// is not time based then this field will not be used and the key is per
// operation. Per operation keys must be user authenticated on each usage.
optional int32 user_auth_key_timeout = 5;
// Track which padding modes this key supports.
repeated string padding = 6;
// Track which digests this key supports
repeated string digest = 7;
// Check what block mode is being used depending on the mode of encryption
repeated string block_mode = 8;
// Was the key generated/imported successfully?
optional bool was_creation_successful = 9;
// What purposes can this key be used for?
repeated string purpose = 10;
// Which ec curve was selected if elliptic curve cryptography is in use
optional string ec_curve = 11;
// Standalone or is a file system required
optional string key_blob_usage_reqs = 12;
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "KeystoreOperation"
#include "key_proto_handler.h"
#include <android/os/DropBoxManager.h>
#include <google/protobuf/message_lite.h>
#include <keymasterV4_0/Keymaster.h>
#include <keystore/keymaster_types.h>
#include <utils/String16.h>
#include "key_config.pb.h"
namespace keystore {
void checkEnforcedCharacteristics(const hidl_vec<KeyParameter>& keyParams, KeyConfig* keyConfig) {
for (auto& keyParam : keyParams) {
switch (keyParam.tag) {
case Tag::PURPOSE:
keyConfig->add_purpose(toString(accessTagValue(TAG_PURPOSE, keyParam)));
break;
case Tag::ALGORITHM:
keyConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, keyParam)));
break;
case Tag::KEY_SIZE:
keyConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, keyParam));
break;
case Tag::BLOCK_MODE:
keyConfig->add_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, keyParam)));
break;
case Tag::PADDING:
keyConfig->add_padding(toString(accessTagValue(TAG_PADDING, keyParam)));
break;
case Tag::DIGEST:
keyConfig->add_digest(toString(accessTagValue(TAG_DIGEST, keyParam)));
break;
case Tag::EC_CURVE:
keyConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, keyParam)));
break;
case Tag::AUTH_TIMEOUT:
keyConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, keyParam));
break;
case Tag::ORIGIN:
keyConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, keyParam)));
break;
case Tag::BLOB_USAGE_REQUIREMENTS:
keyConfig->set_key_blob_usage_reqs(
toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, keyParam)));
break;
case Tag::USER_AUTH_TYPE:
keyConfig->set_user_auth_type(toString(accessTagValue(TAG_USER_AUTH_TYPE, keyParam)));
break;
default:
break;
}
}
}
void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
bool wasCreationSuccessful) {
KeyConfig keyConfig;
checkEnforcedCharacteristics(keyParams, &keyConfig);
auto dropbox = std::make_unique<android::os::DropBoxManager>();
keyConfig.set_was_creation_successful(wasCreationSuccessful);
size_t size = keyConfig.ByteSize();
auto data = std::make_unique<uint8_t[]>(size);
keyConfig.SerializeWithCachedSizesToArray(data.get());
dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
}
} // namespace keystore

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
#define KEYSTORE_KEY_PROTO_HANDLER_H_
#include <keystore/keystore_hidl_support.h>
namespace keystore {
void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
bool wasCreationSuccessful);
} // namespace keystore
#endif // KEYSTORE_KEY_PROTO_HANDLER_H_

View file

@ -38,6 +38,7 @@
#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
#include "defaults.h"
#include "key_proto_handler.h"
#include "keystore_attestation_id.h"
#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
@ -822,6 +823,7 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par
}
if (!error.isOk()) {
ALOGE("Failed to generate key -> falling back to software keymaster");
uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
securityLevel = SecurityLevel::SOFTWARE;
// No fall back for 3DES
@ -847,6 +849,8 @@ KeyStoreService::generateKey(const String16& name, const KeymasterArguments& par
*aidl_return = static_cast<int32_t>(error);
return Status::ok();
}
} else {
uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
}
if (!containsTag(params.getParameters(), Tag::USER_ID)) {
@ -1053,6 +1057,7 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param
// now check error from callback
if (!error.isOk()) {
ALOGE("Failed to import key -> falling back to software keymaster");
uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
securityLevel = SecurityLevel::SOFTWARE;
// No fall back for 3DES
@ -1081,6 +1086,8 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param
*aidl_return = static_cast<int32_t>(error);
return Status::ok();
}
} else {
uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
}
// Write the characteristics:
@ -1338,8 +1345,9 @@ Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name,
// Note: The operation map takes possession of the contents of "characteristics".
// It is safe to use characteristics after the following line but it will be empty.
sp<IBinder> operationToken = mOperationMap.addOperation(
result->handle, keyid, keyPurpose, dev, appToken, std::move(characteristics), pruneable);
sp<IBinder> operationToken =
mOperationMap.addOperation(result->handle, keyid, keyPurpose, dev, appToken,
std::move(characteristics), params.getParameters(), pruneable);
assert(characteristics.hardwareEnforced.size() == 0);
assert(characteristics.softwareEnforced.size() == 0);
result->token = operationToken;
@ -1478,20 +1486,23 @@ Status KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArgument
op.device->finish(op.handle, inParams,
::std::vector<uint8_t>() /* TODO(swillden): wire up input to finish() */,
signature, authToken, VerificationToken(), hidlCb));
// removeOperation() will free the memory 'op' used, so the order is important
mAuthTokenTable.MarkCompleted(op.handle);
mOperationMap.removeOperation(token);
bool wasOpSuccessful = true;
// just a reminder: on success result->resultCode was set in the callback. So we only overwrite
// it if there was a communication error indicated by the ErrorCode.
if (!rc.isOk()) {
result->resultCode = rc;
wasOpSuccessful = false;
}
// removeOperation() will free the memory 'op' used, so the order is important
mAuthTokenTable.MarkCompleted(op.handle);
mOperationMap.removeOperation(token, wasOpSuccessful);
return Status::ok();
}
Status KeyStoreService::abort(const sp<IBinder>& token, int32_t* aidl_return) {
auto getOpResult = mOperationMap.removeOperation(token);
auto getOpResult = mOperationMap.removeOperation(token, false /* wasOpSuccessful */);
if (!getOpResult.isOk()) {
*aidl_return = static_cast<int32_t>(ErrorCode::INVALID_OPERATION_HANDLE);
return Status::ok();

View file

@ -26,18 +26,18 @@ OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
const sp<Keymaster>& dev, const sp<IBinder>& appToken,
KeyCharacteristics&& characteristics, bool pruneable) {
KeyCharacteristics&& characteristics,
const hidl_vec<KeyParameter>& params, bool pruneable) {
sp<IBinder> token = new ::android::BBinder();
mMap.emplace(token,
Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken));
mMap.emplace(token, Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken,
params));
if (pruneable) mLru.push_back(token);
if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
mAppTokenMap[appToken].push_back(token);
return token;
}
NullOr<const OperationMap::Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
NullOr<const Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
auto entry = mMap.find(token);
if (entry == mMap.end()) return {};
@ -53,17 +53,17 @@ void OperationMap::updateLru(const sp<IBinder>& token) {
}
}
NullOr<OperationMap::Operation> OperationMap::removeOperation(const sp<IBinder>& token) {
NullOr<Operation> OperationMap::removeOperation(const sp<IBinder>& token, bool wasSuccessful) {
auto entry = mMap.find(token);
if (entry == mMap.end()) return {};
Operation op = std::move(entry->second);
uploadOpAsProto(op, wasSuccessful);
mMap.erase(entry);
auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
if (lruEntry != mLru.end()) mLru.erase(lruEntry);
removeOperationTracking(token, op.appToken);
return op;
}
@ -109,10 +109,4 @@ std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>&
return appEntry->second;
}
OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
const sp<Keymaster>& device_,
KeyCharacteristics&& characteristics_, sp<IBinder> appToken_)
: handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
characteristics(characteristics_), appToken(appToken_) {}
} // namespace keystore

View file

@ -26,6 +26,10 @@
#include <utils/StrongPointer.h>
#include <keystore/keymaster_types.h>
#include <keystore/keystore_hidl_support.h>
#include "operation_proto_handler.h"
#include "operation_struct.h"
namespace keystore {
@ -42,30 +46,13 @@ using keymaster::support::Keymaster;
class OperationMap {
public:
struct Operation {
Operation() = default;
Operation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, const sp<Keymaster>& device,
KeyCharacteristics&& characteristics, sp<IBinder> appToken);
Operation(Operation&&) = default;
Operation(const Operation&) = delete;
bool hasAuthToken() const { return authToken.mac.size() != 0; }
uint64_t handle;
uint64_t keyid;
KeyPurpose purpose;
sp<Keymaster> device;
KeyCharacteristics characteristics;
sp<IBinder> appToken;
HardwareAuthToken authToken;
};
explicit OperationMap(IBinder::DeathRecipient* deathRecipient);
sp<IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
const sp<Keymaster>& dev, const sp<IBinder>& appToken,
KeyCharacteristics&& characteristics, bool pruneable);
KeyCharacteristics&& characteristics,
const hidl_vec<KeyParameter>& params, bool pruneable);
NullOr<const Operation&> getOperation(const sp<IBinder>& token);
NullOr<Operation> removeOperation(const sp<IBinder>& token);
NullOr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful);
bool hasPruneableOperation() const;
size_t getOperationCount() const { return mMap.size(); }
size_t getPruneableOperationCount() const;

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto2";
package keystore;
option optimize_for = LITE_RUNTIME;
message OperationConfig {
// What type of encryption algorithm is the key being used in the op for.
optional string algorithm = 1;
// Size of the key being used in this op
optional int32 key_size = 2;
// Log whether the key in this op was generated, imported,
// securely imported, or derived.
optional string origin = 3;
// What auth types does this op require? If none, then no auth required.
optional string user_auth_type = 4;
// If user authentication is required, is the requirement time based? If it
// is not time based then this field will not be used and the key is per
// operation. Per operation keys must be user authenticated on each usage.
optional int32 user_auth_key_timeout = 5;
// Track which padding mode was used for this operation.
optional string padding = 6;
// Keep track of the digest algorithm being used.
optional string digest = 7;
// Check what block mode is being used depending on the mode of encryption
optional string block_mode = 8;
// Did the operation succeed? If it didn't, this represents bugs or
// error cases occurring.
optional bool was_op_successful = 9;
// What purpose is this operation serving? Encrypt, decrypt, sign verify?
optional string purpose = 10;
// Which ec curve was selected if elliptic curve cryptography is in use
optional string ec_curve = 11;
// Standalone or is a file system required
optional string key_blob_usage_reqs = 12;
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "KeystoreOperation"
#include "operation_proto_handler.h"
#include <android/os/DropBoxManager.h>
#include <google/protobuf/message_lite.h>
#include <keymasterV4_0/Keymaster.h>
#include <keystore/keymaster_types.h>
#include <keystore/keystore_hidl_support.h>
#include <utils/String16.h>
#include "operation_config.pb.h"
namespace keystore {
void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
switch (purpose) {
case KeyPurpose::VERIFY:
operationConfig->set_purpose("verify");
break;
case KeyPurpose::ENCRYPT:
operationConfig->set_purpose("encrypt");
break;
case KeyPurpose::SIGN:
operationConfig->set_purpose("sign");
break;
case KeyPurpose::DECRYPT:
operationConfig->set_purpose("decrypt");
break;
case KeyPurpose::WRAP_KEY:
operationConfig->set_purpose("wrap");
break;
default:
break;
}
}
void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
OperationConfig* operationConfig) {
for (auto& opParam : characteristics) {
switch (opParam.tag) {
case Tag::ALGORITHM:
operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
break;
case Tag::KEY_SIZE:
operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
break;
case Tag::EC_CURVE:
operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
break;
case Tag::AUTH_TIMEOUT:
operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
break;
case Tag::ORIGIN:
operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
break;
case Tag::BLOB_USAGE_REQUIREMENTS:
operationConfig->set_key_blob_usage_reqs(
toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
break;
case Tag::USER_AUTH_TYPE:
operationConfig->set_user_auth_type(
toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
break;
default:
break;
}
}
}
void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
OperationConfig* operationConfig) {
for (auto& opParam : characteristics) {
switch (opParam.tag) {
case Tag::BLOCK_MODE:
operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
break;
case Tag::PADDING:
operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
break;
case Tag::DIGEST:
operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
break;
default:
break;
}
}
}
void uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
OperationConfig operationConfig;
determinePurpose(op.purpose, &operationConfig);
checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
checkOpCharacteristics(op.params, &operationConfig);
auto dropbox = std::make_unique<android::os::DropBoxManager>();
operationConfig.set_was_op_successful(wasOpSuccessful);
size_t size = operationConfig.ByteSize();
auto data = std::make_unique<uint8_t[]>(size);
operationConfig.SerializeWithCachedSizesToArray(data.get());
dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
}
} // namespace keystore

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef KEYSTORE_OPERATION_PROTO_HANDLER_H_
#define KEYSTORE_OPERATION_PROTO_HANDLER_H_
#include "operation_struct.h"
namespace keystore {
using ::android::IBinder;
using keymaster::support::Keymaster;
void uploadOpAsProto(Operation& op, bool wasOpSuccessful);
} // namespace keystore
#endif // KEYSTORE_OPERATION_PROTO_HANDLER_H_

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef KEYSTORE_OPERATION_STRUCT_H_
#define KEYSTORE_OPERATION_STRUCT_H_
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <keymasterV4_0/Keymaster.h>
#include <utils/StrongPointer.h>
#include <keystore/keymaster_types.h>
#include <keystore/keystore_hidl_support.h>
namespace keystore {
using ::android::IBinder;
using ::android::sp;
using keymaster::support::Keymaster;
struct Operation {
Operation() = default;
Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_, const sp<Keymaster>& device_,
KeyCharacteristics&& characteristics_, sp<IBinder> appToken_,
const hidl_vec<KeyParameter> params_)
: handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
characteristics(characteristics_), appToken(appToken_), params(params_) {}
Operation(Operation&&) = default;
Operation(const Operation&) = delete;
bool hasAuthToken() const { return authToken.mac.size() != 0; }
uint64_t handle;
uint64_t keyid;
KeyPurpose purpose;
sp<Keymaster> device;
KeyCharacteristics characteristics;
sp<IBinder> appToken;
HardwareAuthToken authToken;
const hidl_vec<KeyParameter> params;
};
} // namespace keystore
#endif