1 /*
2 *
3 * Copyright (C) 2017 GlobalLogic
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdbool.h>
22 #include <log/log.h>
23 #include <tee_client_api.h>
24 #include <hardware/keymaster2.h>
25
26 #include <optee_keymaster/ipc/optee_keymaster_ipc.h>
27
28 #undef LOG_TAG
29 #define LOG_TAG "OpteeKeymaster_ipc"
30 #define TA_KEYMASTER_UUID { 0xdba51a17, 0x0563, 0x11e7, \
31 { 0x93, 0xb1, 0x6f, 0xa7, 0xb0, 0x07, 0x1a, 0x51} }
32
33 static TEEC_Context ctx;
34 static TEEC_Session sess;
35 static bool connected = false;
36
optee_keymaster_connect(void)37 int optee_keymaster_connect(void) {
38 TEEC_Result res;
39 TEEC_UUID uuid = TA_KEYMASTER_UUID;
40 uint32_t err_origin;
41
42 if (connected) {
43 ALOGE("Connection with trustled application already established");
44 return false;
45 }
46
47 res = TEEC_InitializeContext(NULL, &ctx);
48 if (res != TEEC_SUCCESS) {
49 ALOGE("TEEC_InitializeContext failed with code 0x%x", res);
50 return (int)res;
51 }
52
53 /* Open a session to the TA */
54 res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC,
55 NULL, NULL, &err_origin);
56 if (res != TEEC_SUCCESS) {
57 ALOGE("TEEC_Opensession failed with code 0x%x origin 0x%x",
58 res, err_origin);
59 return (int)res;
60 }
61 connected = true;
62 ALOGI("Connection with keystore was established");
63 return 0;
64 }
65
optee_keymaster_disconnect(void)66 void optee_keymaster_disconnect(void) {
67 TEEC_CloseSession(&sess);
68 TEEC_FinalizeContext(&ctx);
69 connected = false;
70 }
71
keymaster_error_message(uint32_t error)72 const char* keymaster_error_message(uint32_t error) {
73 switch((int)error) {
74 case (KM_ERROR_OK):
75 return "No error";
76 case (KM_ERROR_UNSUPPORTED_PURPOSE):
77 return "Purpose is unsupported";
78 case (KM_ERROR_INCOMPATIBLE_PURPOSE):
79 return "Purpose is incompatible";
80 case (KM_ERROR_UNSUPPORTED_ALGORITHM):
81 return "Algorithm is unsupported";
82 case (KM_ERROR_INCOMPATIBLE_ALGORITHM):
83 return "Algorithm is incompatible";
84 case (KM_ERROR_UNSUPPORTED_KEY_SIZE):
85 return "Unsupported key size";
86 case (KM_ERROR_UNSUPPORTED_BLOCK_MODE):
87 return "Block mode is unsupported";
88 case (KM_ERROR_INCOMPATIBLE_BLOCK_MODE):
89 return "Block mode is incompatible";
90 case (KM_ERROR_UNSUPPORTED_MAC_LENGTH):
91 return "Mac length is unsupported";
92 case (KM_ERROR_UNSUPPORTED_PADDING_MODE):
93 return "Padding mode is unsupported";
94 case (KM_ERROR_INCOMPATIBLE_PADDING_MODE):
95 return "Padding mode is incompatible";
96 case (KM_ERROR_UNSUPPORTED_DIGEST):
97 return "Digest is unsupported";
98 case (KM_ERROR_INCOMPATIBLE_DIGEST):
99 return "Digest id incompatible";
100 case (KM_ERROR_INVALID_USER_ID):
101 return "User ID is invalid";
102 case (KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT):
103 return "Invalid authorization timeout";
104 case (KM_ERROR_UNSUPPORTED_KEY_FORMAT):
105 return "Key format is unsupported";
106 case (KM_ERROR_INCOMPATIBLE_KEY_FORMAT):
107 return "Key format is incompatible";
108 case (KM_ERROR_INVALID_INPUT_LENGTH):
109 return "Invalid input length";
110 case (KM_ERROR_KEY_EXPORT_OPTIONS_INVALID):
111 return "Key export options invalid";
112 case (KM_ERROR_KEY_USER_NOT_AUTHENTICATED):
113 return "User is not authenticated";
114 case (KM_ERROR_INVALID_OPERATION_HANDLE):
115 return "Operation handle is invalid";
116 case (KM_ERROR_INSUFFICIENT_BUFFER_SPACE):
117 return "Insufficient buffer space";
118 case (KM_ERROR_VERIFICATION_FAILED):
119 return "Verification failed";
120 case (KM_ERROR_TOO_MANY_OPERATIONS):
121 return "Too many operations";
122 case (KM_ERROR_INVALID_KEY_BLOB):
123 return "Key blob is invalid";
124 case (KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED):
125 return "Imported key is not encrypted";
126 case (KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED):
127 return "Imported key decryption failed";
128 case (KM_ERROR_IMPORTED_KEY_NOT_SIGNED):
129 return "Imported key is not signed";
130 case (KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED):
131 return "Imported key verification failed";
132 case (KM_ERROR_INVALID_ARGUMENT):
133 return "Invalid argument";
134 case (KM_ERROR_UNSUPPORTED_TAG):
135 return "Unsupported tag";
136 case (KM_ERROR_INVALID_TAG):
137 return "Invalid tag";
138 case (KM_ERROR_MEMORY_ALLOCATION_FAILED):
139 return "memory allocation failed";
140 case (KM_ERROR_IMPORT_PARAMETER_MISMATCH):
141 return "Import parameters mismatch";
142 case (KM_ERROR_SECURE_HW_ACCESS_DENIED):
143 return "Secure hardware access denied";
144 case (KM_ERROR_OPERATION_CANCELLED):
145 return "Operation was cancelled";
146 case (KM_ERROR_CONCURRENT_ACCESS_CONFLICT):
147 return "Concurent access conflict";
148 case (KM_ERROR_SECURE_HW_BUSY):
149 return "Secure harware is busy";
150 case (KM_ERROR_SECURE_HW_COMMUNICATION_FAILED):
151 return "Secure hardware communication failed";
152 case (KM_ERROR_UNSUPPORTED_EC_FIELD):
153 return "Unsupported EC field";
154 case (KM_ERROR_MISSING_NONCE):
155 return "Missing nonce";
156 case (KM_ERROR_INVALID_NONCE):
157 return "Nonce is invalid";
158 case (KM_ERROR_MISSING_MAC_LENGTH):
159 return "Mac length is missing";
160 case (KM_ERROR_KEY_RATE_LIMIT_EXCEEDED):
161 return "Key rate limit has been exceeded";
162 case (KM_ERROR_CALLER_NONCE_PROHIBITED):
163 return "Caller nonce is prohibited";
164 case (KM_ERROR_KEY_MAX_OPS_EXCEEDED):
165 return "Key max operations has been exceeded";
166 case (KM_ERROR_INVALID_MAC_LENGTH):
167 return "Mac length is invalid";
168 case (KM_ERROR_MISSING_MIN_MAC_LENGTH):
169 return "Min mac length is missing";
170 case (KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH):
171 return "Min mac length is unsupported";
172 case (KM_ERROR_UNSUPPORTED_EC_CURVE):
173 return "Unsupported EC curve";
174 case (KM_ERROR_KEY_REQUIRES_UPGRADE):
175 return "Key requeres upgrade";
176 case (KM_ERROR_ATTESTATION_CHALLENGE_MISSING):
177 return "Attestation challenge missing";
178 case (KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING):
179 return "Attestation application ID missing";
180 case (KM_ERROR_KEYMASTER_NOT_CONFIGURED):
181 return "Keymaster is not configured";
182 case (KM_ERROR_UNIMPLEMENTED):
183 return "Feature is not implemented";
184 case (KM_ERROR_VERSION_MISMATCH):
185 return "Version mismatch";
186 default:
187 return "Unknown error";
188 }
189 }
190
optee_keymaster_send(uint32_t command,const keymaster::Serializable & req,keymaster::KeymasterResponse * rsp)191 keymaster_error_t optee_keymaster_send(uint32_t command, const keymaster::Serializable& req,
192 keymaster::KeymasterResponse* rsp) {
193 TEEC_Operation op;
194 uint32_t res;
195 uint32_t err_origin;
196
197 if (!connected) {
198 ALOGE("Keystore trusted application is not connected");
199 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
200 }
201
202 (void)memset(&op, 0, sizeof(op));
203
204 uint32_t req_size = req.SerializedSize();
205 if (req_size > OPTEE_KEYMASTER_SEND_BUF_SIZE) {
206 ALOGE("Request too big: %u Max size: %u", req_size,
207 OPTEE_KEYMASTER_SEND_BUF_SIZE);
208 return KM_ERROR_INVALID_INPUT_LENGTH;
209 }
210
211 uint8_t send_buf[OPTEE_KEYMASTER_SEND_BUF_SIZE];
212 keymaster::Eraser send_buf_eraser(send_buf, OPTEE_KEYMASTER_SEND_BUF_SIZE);
213 req.Serialize(send_buf, send_buf + req_size);
214
215 /* Send it */
216 uint8_t recv_buf[OPTEE_KEYMASTER_RECV_BUF_SIZE];
217 keymaster::Eraser recv_buf_eraser(recv_buf, OPTEE_KEYMASTER_RECV_BUF_SIZE);
218 uint32_t rsp_size = OPTEE_KEYMASTER_RECV_BUF_SIZE;
219 op.paramTypes = (uint32_t)TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
220 TEEC_MEMREF_TEMP_OUTPUT,
221 TEEC_NONE,
222 TEEC_NONE);
223 op.params[0].tmpref.buffer = (void*)send_buf;
224 op.params[0].tmpref.size = req_size;
225 op.params[1].tmpref.buffer = (void*)recv_buf;
226 op.params[1].tmpref.size = rsp_size;
227
228 res = TEEC_InvokeCommand(&sess, command, &op, &err_origin);
229 if (res != TEEC_SUCCESS) {
230 ALOGI("TEEC_InvokeCommand command %d failed with code 0x%08x (%s) origin "
231 "0x%08x", command, res, keymaster_error_message(res), err_origin);
232 if (res == TEEC_ERROR_TARGET_DEAD) {
233 optee_keymaster_disconnect();
234 optee_keymaster_connect();
235 }
236 }
237
238 const uint8_t* p = recv_buf;
239 if (!rsp->Deserialize(&p, p + rsp_size)) {
240 ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
241 return KM_ERROR_UNKNOWN_ERROR;
242 } else if (rsp->error != KM_ERROR_OK) {
243 ALOGE("Response of size %d contained error code %d\n", (int)rsp_size,
244 (int)rsp->error);
245 } else if (res != KM_ERROR_OK) {
246 /*
247 * rsp->error is KM_ERROR_OK but res isn't? This happens when:
248 * 1. param_types != exp_param_types in TA_InvokeCommandEntryPoint()
249 * 2. req or rsp (in or out bufptr in keystore_ta.c) are NULL
250 * so res can't be serialized into rsp
251 * 3. rsp_size (out_size) != OPTEE_KEYMASTER_RECV_BUF_SIZE
252 * (KM_RECV_BUF_SIZE) in keystore_ta.c
253 * 4. error writing past the end of recv_buf, i.e. writing past out_end
254 * in keystore_ta.c
255 */
256 ALOGE("Response of size %d contained error code %d\n", (int)rsp_size,
257 (int)res);
258 return (keymaster_error_t)res;
259 }
260
261 return rsp->error;
262 }
263