1 /*
2 * Copyright 2021, 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
17 #include <trusty_keymaster/TrustyKeyMintOperation.h>
18
19 #define TAG TrustyKeyMintOperation
20 #include <android-base/logging.h>
21
22 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
23 #include <aidl/android/hardware/security/secureclock/ISecureClock.h>
24
25 #include <KeyMintUtils.h>
26 #include <keymaster/android_keymaster.h>
27 #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
28
29 namespace aidl::android::hardware::security::keymint {
30
31 using ::keymaster::AbortOperationRequest;
32 using ::keymaster::AbortOperationResponse;
33 using ::keymaster::FinishOperationRequest;
34 using ::keymaster::FinishOperationResponse;
35 using ::keymaster::TAG_ASSOCIATED_DATA;
36 using ::keymaster::TAG_AUTH_TOKEN;
37 using ::keymaster::TAG_CONFIRMATION_TOKEN;
38 using ::keymaster::UpdateOperationRequest;
39 using ::keymaster::UpdateOperationResponse;
40 using km_utils::authToken2AidlVec;
41 using km_utils::kmError2ScopedAStatus;
42 using secureclock::TimeStampToken;
43
TrustyKeyMintOperation(shared_ptr<TrustyKeymaster> implementation,keymaster_operation_handle_t opHandle)44 TrustyKeyMintOperation::TrustyKeyMintOperation(shared_ptr<TrustyKeymaster> implementation,
45 keymaster_operation_handle_t opHandle)
46 : impl_(std::move(implementation)), opHandle_(opHandle) {}
47
~TrustyKeyMintOperation()48 TrustyKeyMintOperation::~TrustyKeyMintOperation() {
49 if (opHandle_ != 0) {
50 abort();
51 }
52 }
53
updateAad(const vector<uint8_t> & input,const optional<HardwareAuthToken> & authToken,const optional<TimeStampToken> &)54 ScopedAStatus TrustyKeyMintOperation::updateAad(
55 const vector<uint8_t>& input, const optional<HardwareAuthToken>& authToken,
56 const optional<TimeStampToken>& /* timestampToken */) {
57 UpdateOperationRequest request(impl_->message_version());
58 request.op_handle = opHandle_;
59 request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(), input.size());
60 if (authToken) {
61 auto tokenAsVec(authToken2AidlVec(*authToken));
62 request.additional_params.push_back(TAG_AUTH_TOKEN, tokenAsVec.data(), tokenAsVec.size());
63 }
64
65 UpdateOperationResponse response(impl_->message_version());
66 impl_->UpdateOperation(request, &response);
67
68 return kmError2ScopedAStatus(response.error);
69 }
70
update(const vector<uint8_t> & input,const optional<HardwareAuthToken> & authToken,const optional<TimeStampToken> &,vector<uint8_t> * output)71 ScopedAStatus TrustyKeyMintOperation::update(const vector<uint8_t>& input,
72 const optional<HardwareAuthToken>& authToken,
73 const optional<TimeStampToken>& /* timestampToken */,
74 vector<uint8_t>* output) {
75 if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
76
77 UpdateOperationRequest request(impl_->message_version());
78 request.op_handle = opHandle_;
79 if (authToken) {
80 auto tokenAsVec(authToken2AidlVec(*authToken));
81 request.additional_params.push_back(TAG_AUTH_TOKEN, tokenAsVec.data(), tokenAsVec.size());
82 }
83
84 size_t serialized_size = request.SerializedSize();
85 if (serialized_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
86 return kmError2ScopedAStatus(KM_ERROR_INVALID_INPUT_LENGTH);
87 }
88
89 const uint8_t* input_pos = input.data();
90 const uint8_t* input_end = input.data() + input.size();
91 const size_t max_chunk_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - serialized_size;
92 output->clear();
93
94 while (input_pos < input_end) {
95 size_t to_send = std::min(max_chunk_size, static_cast<size_t>(input_end - input_pos));
96 LOG(DEBUG) << "update: Sending " << to_send << " of " << (input_end - input_pos)
97 << " bytes";
98 request.input.Reinitialize(input_pos, to_send);
99
100 UpdateOperationResponse response(impl_->message_version());
101 impl_->UpdateOperation(request, &response);
102 if (response.error != KM_ERROR_OK) {
103 opHandle_ = 0; // Operation has ended, the handle is invalid. This saves an abort().
104 return kmError2ScopedAStatus(response.error);
105 }
106
107 input_pos += response.input_consumed;
108 output->insert(output->end(), response.output.begin(), response.output.end());
109 }
110
111 return ScopedAStatus::ok();
112 }
113
finish(const optional<vector<uint8_t>> & input,const optional<vector<uint8_t>> & signature,const optional<HardwareAuthToken> & authToken,const optional<TimeStampToken> &,const optional<vector<uint8_t>> & confirmationToken,vector<uint8_t> * output)114 ScopedAStatus TrustyKeyMintOperation::finish(const optional<vector<uint8_t>>& input, //
115 const optional<vector<uint8_t>>& signature, //
116 const optional<HardwareAuthToken>& authToken,
117 const optional<TimeStampToken>& /* timestampToken */,
118 const optional<vector<uint8_t>>& confirmationToken,
119 vector<uint8_t>* output) {
120 if (!output) {
121 return ScopedAStatus(AStatus_fromServiceSpecificError(
122 static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
123 }
124 output->clear();
125
126 FinishOperationRequest request(impl_->message_version());
127
128 if (authToken) {
129 auto tokenAsVec(authToken2AidlVec(*authToken));
130 request.additional_params.push_back(TAG_AUTH_TOKEN, tokenAsVec.data(), tokenAsVec.size());
131 }
132 if (confirmationToken) {
133 request.additional_params.push_back(TAG_CONFIRMATION_TOKEN, confirmationToken->data(),
134 confirmationToken->size());
135 }
136
137 request.op_handle = opHandle_;
138 if (signature) request.signature.Reinitialize(signature->data(), signature->size());
139 size_t serialized_size = request.SerializedSize();
140 if (serialized_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
141 return kmError2ScopedAStatus(KM_ERROR_INVALID_INPUT_LENGTH);
142 }
143
144 if (input) {
145 const size_t max_chunk_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - serialized_size;
146
147 if (input->size() > max_chunk_size) {
148 LOG(DEBUG) << "Sending an update to process finish() data";
149 // Use update to process all but the last max_chunk_size bytes.
150 auto result = update({input->begin(), input->end() - max_chunk_size}, authToken,
151 std::nullopt /* timestampToken */, output);
152 if (!result.isOk()) return result;
153
154 // Process the last max_chunk_size with finish.
155 request.input.Reinitialize(input->data() + (input->size() - max_chunk_size),
156 max_chunk_size);
157 } else {
158 request.input.Reinitialize(input->data(), input->size());
159 }
160 }
161
162 FinishOperationResponse response(impl_->message_version());
163 impl_->FinishOperation(request, &response);
164 opHandle_ = 0;
165
166 if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
167
168 *output = {response.output.begin(), response.output.end()};
169 return ScopedAStatus::ok();
170 }
171
abort()172 ScopedAStatus TrustyKeyMintOperation::abort() {
173 AbortOperationRequest request(impl_->message_version());
174 request.op_handle = opHandle_;
175
176 AbortOperationResponse response(impl_->message_version());
177 impl_->AbortOperation(request, &response);
178 opHandle_ = 0;
179
180 return kmError2ScopedAStatus(response.error);
181 }
182
183 } // namespace aidl::android::hardware::security::keymint
184