summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasini Gunasinghe <hasinitg@google.com>2020-06-15 16:40:07 +0000
committerHasini Gunasinghe <hasinitg@google.com>2020-06-15 16:44:54 +0000
commit0dab3eb11f8d78287875a10abf761715474d037d (patch)
tree0e2f73f3d66dbe9901151a71286ead85233a8cd5
parent0e88123f7da68590feaa81ec143b388bef901e00 (diff)
downloadsecurity-0dab3eb11f8d78287875a10abf761715474d037d.tar.gz
Log keystore key operation events using statsd.
This is the second CL on migrating keystore logging to statsd. This migrates the logging for key operation events. Three new ResponseCodes are added for the logging purpose of the abort operations. Test: Adding tests for logging is yet to be decided. Change-Id: I68c1d89beeb733e4b6ba493b8d95935b7e73df60 Bug: 157664923
-rw-r--r--keystore/Android.bp3
-rw-r--r--keystore/include/keystore/keystore.h14
-rw-r--r--keystore/key_operation_log_handler.cpp136
-rw-r--r--keystore/key_operation_log_handler.h (renamed from keystore/operation_proto_handler.h)24
-rw-r--r--keystore/keymaster_worker.cpp19
-rw-r--r--keystore/keymaster_worker.h2
-rw-r--r--keystore/operation.cpp5
-rw-r--r--keystore/operation.h5
-rw-r--r--keystore/operation_config.proto77
-rw-r--r--keystore/operation_proto_handler.cpp147
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