blob: 1833acb32f2ad7d45c0262bea50640317fe8fe87 [file] [log] [blame]
Max Bires33aac2d2018-02-23 10:53:10 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#define LOG_TAG "KeystoreOperation"
17
18#include "operation_proto_handler.h"
19
20#include <android/os/DropBoxManager.h>
21#include <google/protobuf/message_lite.h>
22#include <keymasterV4_0/Keymaster.h>
23#include <keystore/keymaster_types.h>
24#include <keystore/keystore_hidl_support.h>
25#include <utils/String16.h>
Hans Boehm4055c3f2018-05-08 15:19:14 -070026#include <utils/StrongPointer.h>
Max Bires33aac2d2018-02-23 10:53:10 -080027
Max Bires091ed1b2018-12-05 12:13:30 -080028using namespace std::chrono;
Max Bires33aac2d2018-02-23 10:53:10 -080029
30namespace keystore {
31
Max Bires091ed1b2018-12-05 12:13:30 -080032constexpr auto kCollectionTime = 1h;
33
Max Bires33aac2d2018-02-23 10:53:10 -080034void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
35 switch (purpose) {
36 case KeyPurpose::VERIFY:
37 operationConfig->set_purpose("verify");
38 break;
39 case KeyPurpose::ENCRYPT:
40 operationConfig->set_purpose("encrypt");
41 break;
42 case KeyPurpose::SIGN:
43 operationConfig->set_purpose("sign");
44 break;
45 case KeyPurpose::DECRYPT:
46 operationConfig->set_purpose("decrypt");
47 break;
48 case KeyPurpose::WRAP_KEY:
49 operationConfig->set_purpose("wrap");
50 break;
51 default:
52 break;
53 }
54}
55
56void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
57 OperationConfig* operationConfig) {
58 for (auto& opParam : characteristics) {
59 switch (opParam.tag) {
60 case Tag::ALGORITHM:
61 operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
62 break;
63 case Tag::KEY_SIZE:
64 operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
65 break;
66 case Tag::EC_CURVE:
67 operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
68 break;
69 case Tag::AUTH_TIMEOUT:
70 operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
71 break;
72 case Tag::ORIGIN:
73 operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
74 break;
75 case Tag::BLOB_USAGE_REQUIREMENTS:
76 operationConfig->set_key_blob_usage_reqs(
77 toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
78 break;
79 case Tag::USER_AUTH_TYPE:
80 operationConfig->set_user_auth_type(
81 toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
82 break;
83 default:
84 break;
85 }
86 }
87}
88
89void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
90 OperationConfig* operationConfig) {
91 for (auto& opParam : characteristics) {
92 switch (opParam.tag) {
93 case Tag::BLOCK_MODE:
94 operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
95 break;
96 case Tag::PADDING:
97 operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
98 break;
99 case Tag::DIGEST:
100 operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
101 break;
102 default:
103 break;
104 }
105 }
106}
107
Max Bires091ed1b2018-12-05 12:13:30 -0800108void OperationProtoHandler::uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
Max Bires33aac2d2018-02-23 10:53:10 -0800109 OperationConfig operationConfig;
110 determinePurpose(op.purpose, &operationConfig);
111 checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
112 checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
113 checkOpCharacteristics(op.params, &operationConfig);
Max Bires33aac2d2018-02-23 10:53:10 -0800114 operationConfig.set_was_op_successful(wasOpSuccessful);
Max Bires091ed1b2018-12-05 12:13:30 -0800115 // Only bother with counting an hour out when an operation entry is actually
116 // added
117 if (protoMap.empty()) {
118 start_time = std::chrono::steady_clock::now();
119 }
120 auto cur_time = std::chrono::steady_clock::now();
Max Bires33aac2d2018-02-23 10:53:10 -0800121
Max Bires091ed1b2018-12-05 12:13:30 -0800122 // Add operations to a map within the time duration of an hour. Deduplicate
123 // repeated ops by incrementing the counter of the original one stored and
124 // discarding the new one.
125 protoMap[operationConfig.SerializeAsString()]++;
126
127 if (cur_time - start_time >= kCollectionTime) {
128 // Iterate through the unordered map and dump all the operation protos
129 // accumulated over the hour into the holding list proto after setting
130 // their counts.
131 OperationConfigEvents opConfigEvents;
132 for (auto elem : protoMap) {
133 OperationConfigEvent* event = opConfigEvents.add_op_config_events();
134 event->mutable_op_config()->ParseFromString(elem.first);
135 event->set_count(elem.second);
136 }
137 android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager);
138 size_t size = opConfigEvents.ByteSize();
139 auto data = std::make_unique<uint8_t[]>(size);
140 opConfigEvents.SerializeWithCachedSizesToArray(data.get());
141 dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
142 protoMap.clear();
143 }
Max Bires33aac2d2018-02-23 10:53:10 -0800144}
145
146} // namespace keystore