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