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:
parent
cf91dcdee3
commit
33aac2dda2
12 changed files with 488 additions and 39 deletions
|
@ -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",
|
||||
|
|
|
@ -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
62
keystore/key_config.proto
Normal 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;
|
||||
}
|
86
keystore/key_proto_handler.cpp
Normal file
86
keystore/key_proto_handler.cpp
Normal 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
|
29
keystore/key_proto_handler.h
Normal file
29
keystore/key_proto_handler.h
Normal 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_
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
63
keystore/operation_config.proto
Normal file
63
keystore/operation_config.proto
Normal 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;
|
||||
}
|
120
keystore/operation_proto_handler.cpp
Normal file
120
keystore/operation_proto_handler.cpp
Normal 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
|
31
keystore/operation_proto_handler.h
Normal file
31
keystore/operation_proto_handler.h
Normal 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_
|
58
keystore/operation_struct.h
Normal file
58
keystore/operation_struct.h
Normal 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
|
Loading…
Reference in a new issue