diff options
author | Hasini Gunasinghe <hasinitg@google.com> | 2020-06-18 15:00:12 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-06-18 15:00:12 +0000 |
commit | f99f40e089ea6ab45aeb8773a02c45612f05409c (patch) | |
tree | 0e2f73f3d66dbe9901151a71286ead85233a8cd5 | |
parent | 80e634486d169302e50adf84d34f28dce0de9916 (diff) | |
parent | 0dab3eb11f8d78287875a10abf761715474d037d (diff) | |
download | security-f99f40e089ea6ab45aeb8773a02c45612f05409c.tar.gz |
Log keystore key operation events using statsd. am: 0dab3eb11f
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/security/+/11869299
Change-Id: I3a1400bc6aa4a77344f2dbc8fdaad75bfe5f093a
-rw-r--r-- | keystore/Android.bp | 3 | ||||
-rw-r--r-- | keystore/include/keystore/keystore.h | 14 | ||||
-rw-r--r-- | keystore/key_operation_log_handler.cpp | 136 | ||||
-rw-r--r-- | keystore/key_operation_log_handler.h (renamed from keystore/operation_proto_handler.h) | 24 | ||||
-rw-r--r-- | keystore/keymaster_worker.cpp | 19 | ||||
-rw-r--r-- | keystore/keymaster_worker.h | 2 | ||||
-rw-r--r-- | keystore/operation.cpp | 5 | ||||
-rw-r--r-- | keystore/operation.h | 5 | ||||
-rw-r--r-- | keystore/operation_config.proto | 77 | ||||
-rw-r--r-- | keystore/operation_proto_handler.cpp | 147 |
10 files changed, 172 insertions, 260 deletions
diff --git a/keystore/Android.bp b/keystore/Android.bp index b41ad183..eb0009fb 100644 --- a/keystore/Android.bp +++ b/keystore/Android.bp @@ -35,6 +35,7 @@ cc_binary { "confirmation_manager.cpp", "grant_store.cpp", "key_creation_log_handler.cpp", + "key_operation_log_handler.cpp", "key_store_service.cpp", "keyblob_utils.cpp", "keymaster_enforcement.cpp", @@ -43,8 +44,6 @@ cc_binary { "keystore_utils.cpp", "legacy_keymaster_device_wrapper.cpp", "operation.cpp", - "operation_config.proto", - "operation_proto_handler.cpp", "permissions.cpp", "user_state.cpp", ], diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h index 3aed8c2f..ab6c6829 100644 --- a/keystore/include/keystore/keystore.h +++ b/keystore/include/keystore/keystore.h @@ -45,6 +45,20 @@ enum class ResponseCode : int32_t { OP_AUTH_NEEDED = 15, // Auth is needed for this operation before it can be used. KEY_ALREADY_EXISTS = 16, KEY_PERMANENTLY_INVALIDATED = 17, + + /** + * Following three response codes are for logging purposes only. + * The operations are logged at the end of the life cycle of an operation handle, + * along with the reason for the end of the operation handle. For the operations + * that fail in update and finish, the reason for failure is available with + * the above response codes. + * For the operations that are aborted in three different ways, the reason + * for aborting is not available. The following enum values define the + * three ways an operation can get aborted. + */ + ABORT_CALLED = 18, + PRUNED = 19, + BINDER_DIED = 20, }; /* diff --git a/keystore/key_operation_log_handler.cpp b/keystore/key_operation_log_handler.cpp new file mode 100644 index 00000000..e7f43457 --- /dev/null +++ b/keystore/key_operation_log_handler.cpp @@ -0,0 +1,136 @@ +/* + * 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_operation_log_handler.h" +#include "key_creation_log_handler.h" + +#include <keystore/keystore_hidl_support.h> +#include <statslog.h> + +namespace keystore { + +template <typename Tag> +int32_t getOptionalEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) { + auto tagValue = authorization_set.GetTagValue(tag); + if (tagValue.isOk()) { + static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t), + "Tag type value will be truncated, if cast to int32_t"); + return static_cast<int32_t>(tagValue.value()); + } + //-1 is an invalid value for all enum types. + return -1; +} + +int32_t generateBitMapForPaddingModeValue(const AuthorizationSet& authorization_set) { + auto tagValue = authorization_set.GetTagValue(TAG_PADDING); + if (tagValue.isOk()) { + auto value = tagValue.value(); + switch (value) { + case PaddingMode::NONE: + return (1 << NONE_BIT_POS); + case PaddingMode::RSA_OAEP: + return (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS); + case PaddingMode::RSA_PSS: + return (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS); + case PaddingMode::RSA_PKCS1_1_5_ENCRYPT: + return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS); + case PaddingMode::RSA_PKCS1_1_5_SIGN: + return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS); + case PaddingMode::PKCS7: + return (1 << PaddingModeBitPosition::PKCS7_BIT_POS); + default: + break; + } + } + // unlike in the single enum fields, if no value is provided, + // 0 is set for the bitmap + return 0; +} + +int32_t generateBitMapForDigestValue(const AuthorizationSet& authorization_set) { + auto tagValue = authorization_set.GetTagValue(TAG_DIGEST); + if (tagValue.isOk()) { + auto value = tagValue.value(); + switch (value) { + case Digest::NONE: + return (1 << NONE_BIT_POS); + case Digest::MD5: + return (1 << DigestBitPosition::MD5_BIT_POS); + case Digest::SHA1: + return (1 << DigestBitPosition::SHA1_BIT_POS); + case Digest::SHA_2_224: + return (1 << DigestBitPosition::SHA_2_224_BIT_POS); + case Digest::SHA_2_256: + return (1 << DigestBitPosition::SHA_2_256_BIT_POS); + case Digest::SHA_2_384: + return (1 << DigestBitPosition::SHA_2_384_BIT_POS); + case Digest::SHA_2_512: + return (1 << DigestBitPosition::SHA_2_512_BIT_POS); + default: + break; + } + } + // unlike in the single enum fields, if no value is provided, + // 0 is set for the bitmap + return 0; +} + +int32_t generateBitMapForBlockModeValue(const AuthorizationSet& authorization_set) { + auto tagValue = authorization_set.GetTagValue(TAG_BLOCK_MODE); + if (tagValue.isOk()) { + auto value = tagValue.value(); + switch (value) { + case BlockMode::ECB: + return (1 << BlockModeBitPosition::ECB_BIT_POS); + case BlockMode::CBC: + return (1 << BlockModeBitPosition::CBC_BIT_POS); + case BlockMode::CTR: + return (1 << BlockModeBitPosition::CTR_BIT_POS); + case BlockMode::GCM: + return (1 << BlockModeBitPosition::GCM_BIT_POS); + default: + break; + } + } + // unlike in the single enum fields, if no value is provided, + // 0 is set for the bitmap + return 0; +} + +void logKeystoreKeyOperationEvent(const Operation& op, bool wasOperationSuccessful, + int32_t responseCode) { + AuthorizationSet authorization_set(op.characteristics.softwareEnforced); + authorization_set.Union(op.characteristics.hardwareEnforced); + AuthorizationSet operation_params(op.params); + + android::util::stats_write( + android::util::KEYSTORE_KEY_EVENT_REPORTED, + getOptionalEnumTagValue(authorization_set, TAG_ALGORITHM), + getOptionalEnumTagValue(authorization_set, TAG_KEY_SIZE), + getOptionalEnumTagValue(authorization_set, TAG_ORIGIN), + getOptionalEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE), + getOptionalEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT), + generateBitMapForPaddingModeValue(operation_params), + generateBitMapForDigestValue(operation_params), + generateBitMapForBlockModeValue(operation_params), static_cast<int32_t>(op.purpose), + getOptionalEnumTagValue(authorization_set, TAG_EC_CURVE), + getOptionalEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS), + android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_OPERATION, wasOperationSuccessful, + responseCode); +} + +} // namespace keystore
\ No newline at end of file diff --git a/keystore/operation_proto_handler.h b/keystore/key_operation_log_handler.h index 64d0a594..ba277470 100644 --- a/keystore/operation_proto_handler.h +++ b/keystore/key_operation_log_handler.h @@ -14,31 +14,15 @@ * limitations under the License. */ -#ifndef KEYSTORE_OPERATION_PROTO_HANDLER_H_ -#define KEYSTORE_OPERATION_PROTO_HANDLER_H_ +#ifndef KEY_OPERATION_LOG_HANDLER_H_ +#define KEY_OPERATION_LOG_HANDLER_H_ -#include "operation_config.pb.h" #include "operation_struct.h" -#include <chrono> -#include <mutex> -#include <unordered_map> -#include <vector> namespace keystore { -using ::android::IBinder; -using keymaster::support::Keymaster; - -class OperationProtoHandler { - public: - void uploadOpAsProto(Operation& op, bool wasOpSuccessful); - - private: - std::unordered_map<std::string, int> protoMap; - std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now(); - std::mutex op_upload_mutex; -}; +void logKeystoreKeyOperationEvent(const Operation& op, bool wasSuccessful, int32_t errorCode); } // namespace keystore -#endif // KEYSTORE_OPERATION_PROTO_HANDLER_H_ +#endif // KEY_OPERATION_LOG_HANDLER_H_
\ No newline at end of file diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp index e7fcf96a..7481a1e5 100644 --- a/keystore/keymaster_worker.cpp +++ b/keystore/keymaster_worker.cpp @@ -336,8 +336,10 @@ KeymasterWorker::getAuthToken(const KeyCharacteristics& characteristics, uint64_ return {rc, std::move(authToken)}; } -KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token) { - auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */); +KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token, + ResponseCode reason_for_abort) { + auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */, + static_cast<int32_t>(reason_for_abort)); if (op) { keyStore_->getAuthTokenTable().MarkCompleted(op->handle); return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); @@ -355,7 +357,7 @@ bool KeymasterWorker::pruneOperation() { size_t op_count_before_abort = operationMap_.getOperationCount(); // We mostly ignore errors from abort() because all we care about is whether at least // one operation has been removed. - auto rc = abort(oldest); + auto rc = abort(oldest, ResponseCode::PRUNED); keyStore_->removeOperationDevice(oldest); if (operationMap_.getOperationCount() >= op_count_before_abort) { ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), rc.getErrorCode()); @@ -598,7 +600,7 @@ void KeymasterWorker::update(sp<IBinder> token, AuthorizationSet params, hidl_ve } Finalize abort_operation_in_case_of_error([&] { - operationMap_.removeOperation(token, false); + operationMap_.removeOperation(token, false, rc.getErrorCode()); keyStore_->getAuthTokenTable().MarkCompleted(op->handle); KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); }); @@ -677,7 +679,7 @@ void KeymasterWorker::finish(sp<IBinder> token, AuthorizationSet params, hidl_ve bool finished = false; Finalize abort_operation_in_case_of_error([&] { - operationMap_.removeOperation(token, finished && rc.isOk()); + operationMap_.removeOperation(token, finished && rc.isOk(), rc.getErrorCode()); keyStore_->getAuthTokenTable().MarkCompleted(op->handle); if (!finished) KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); @@ -745,8 +747,9 @@ void KeymasterWorker::finish(sp<IBinder> token, AuthorizationSet params, hidl_ve } void KeymasterWorker::abort(sp<IBinder> token, abort_cb worker_cb) { - Worker::addRequest( - [this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() { return worker_cb(abort(token)); }); + Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() { + return worker_cb(abort(token, ResponseCode::ABORT_CALLED)); + }); } void KeymasterWorker::verifyAuthorization(uint64_t challenge, hidl_vec<KeyParameter> params, @@ -1132,7 +1135,7 @@ void KeymasterWorker::binderDied(android::wp<IBinder> who) { Worker::addRequest([this, who]() { auto operations = operationMap_.getOperationsForToken(who.unsafe_get()); for (const auto& token : operations) { - abort(token); + abort(token, ResponseCode::BINDER_DIED); keyStore_->removeOperationDevice(token); } }); diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h index 8e35c16f..f11af297 100644 --- a/keystore/keymaster_worker.h +++ b/keystore/keymaster_worker.h @@ -190,7 +190,7 @@ class KeymasterWorker : protected Worker { getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose, bool failOnTokenMissing = true); - KeyStoreServiceReturnCode abort(const sp<IBinder>& token); + KeyStoreServiceReturnCode abort(const sp<IBinder>& token, ResponseCode reason_for_abort); bool pruneOperation(); diff --git a/keystore/operation.cpp b/keystore/operation.cpp index 71ab3405..bd4bd5ef 100644 --- a/keystore/operation.cpp +++ b/keystore/operation.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "KeystoreOperation" #include "operation.h" +#include "key_operation_log_handler.h" #include <algorithm> #include <android-base/logging.h> @@ -58,12 +59,12 @@ void OperationMap::updateLru(const sp<IBinder>& token) { } std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& token, - bool wasSuccessful) { + bool wasSuccessful, int32_t responseCode) { auto entry = mMap.find(token); if (entry == mMap.end()) return {}; auto op = entry->second; - operationUploader.uploadOpAsProto(*op, wasSuccessful); + logKeystoreKeyOperationEvent(*op, wasSuccessful, responseCode); mMap.erase(entry); auto lruEntry = std::find(mLru.begin(), mLru.end(), token); diff --git a/keystore/operation.h b/keystore/operation.h index ef880a75..8423db5b 100644 --- a/keystore/operation.h +++ b/keystore/operation.h @@ -33,7 +33,6 @@ #include <keystore/keystore_concurrency.h> #include <keystore/keystore_hidl_support.h> -#include "operation_proto_handler.h" #include "operation_struct.h" namespace keystore { @@ -57,7 +56,8 @@ class OperationMap { KeyCharacteristics&& characteristics, const hidl_vec<KeyParameter>& params, bool pruneable); std::shared_ptr<Operation> getOperation(const sp<IBinder>& token); - std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful); + std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful, + int32_t responseCode); size_t getOperationCount() const { return mMap.size(); } sp<IBinder> getOldestPruneableOperation(); std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken); @@ -70,7 +70,6 @@ class OperationMap { std::list<sp<IBinder>> mLru; std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap; IBinder::DeathRecipient* mDeathRecipient; - OperationProtoHandler operationUploader; }; } // namespace keystore diff --git a/keystore/operation_config.proto b/keystore/operation_config.proto deleted file mode 100644 index efbb4fed..00000000 --- a/keystore/operation_config.proto +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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; - -// A single operation config -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; -} - -message OperationConfigEvent { - optional OperationConfig op_config = 1; - - // counts corresponds to the number of times each op_config in the above array - // was recorded during the collection period. - optional uint32 count = 2; -} - -message OperationConfigEvents { - repeated OperationConfigEvent op_config_events = 1; -} - diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp deleted file mode 100644 index 3b3d3fc3..00000000 --- a/keystore/operation_proto_handler.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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_1/Keymaster.h> -#include <keystore/keymaster_types.h> -#include <keystore/keystore_hidl_support.h> -#include <utils/String16.h> -#include <utils/StrongPointer.h> - -using namespace std::chrono; - -namespace keystore { - -constexpr auto kCollectionTime = 1h; - -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 OperationProtoHandler::uploadOpAsProto(Operation& op, bool wasOpSuccessful) { - std::lock_guard<std::mutex> lock(op_upload_mutex); - OperationConfig operationConfig; - determinePurpose(op.purpose, &operationConfig); - checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig); - checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig); - checkOpCharacteristics(op.params, &operationConfig); - operationConfig.set_was_op_successful(wasOpSuccessful); - // Only bother with counting an hour out when an operation entry is actually - // added - if (protoMap.empty()) { - start_time = std::chrono::steady_clock::now(); - } - auto cur_time = std::chrono::steady_clock::now(); - - // Add operations to a map within the time duration of an hour. Deduplicate - // repeated ops by incrementing the counter of the original one stored and - // discarding the new one. - protoMap[operationConfig.SerializeAsString()]++; - - if (cur_time - start_time >= kCollectionTime) { - // Iterate through the unordered map and dump all the operation protos - // accumulated over the hour into the holding list proto after setting - // their counts. - OperationConfigEvents opConfigEvents; - for (auto elem : protoMap) { - OperationConfigEvent* event = opConfigEvents.add_op_config_events(); - event->mutable_op_config()->ParseFromString(elem.first); - event->set_count(elem.second); - } - android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager); - size_t size = opConfigEvents.ByteSize(); - auto data = std::make_unique<uint8_t[]>(size); - opConfigEvents.SerializeWithCachedSizesToArray(data.get()); - dropbox->addData(android::String16("keymaster"), data.get(), size, 0); - protoMap.clear(); - } -} - -} // namespace keystore |