1 /*
2 * Copyright (C) 2015 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 <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <trusty_ipc.h>
21 #include <uapi/err.h>
22
23 #include <dice/cbor_reader.h>
24 #include <interface/keymaster/keymaster.h>
25 #include <lib/keymaster/keymaster.h>
26
27 #include <openssl/hmac.h>
28
29 #define LOG_TAG "libkeymaster"
30 #define TLOGE(fmt, ...) \
31 fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__, ##__VA_ARGS__)
32
33 #define HMAC_LEN (sizeof(((hw_auth_token_t*)0)->hmac))
34
35 #define AUTH_TOKEN_KEY_LEN (32)
36
send_req(keymaster_session_t session,uint32_t cmd)37 static long send_req(keymaster_session_t session, uint32_t cmd) {
38 struct keymaster_message msg = {
39 .cmd = cmd,
40 };
41
42 struct iovec tx_iov = {
43 .iov_base = &msg,
44 .iov_len = sizeof(msg),
45 };
46 ipc_msg_t tx_msg = {
47 .iov = &tx_iov,
48 .num_iov = 1,
49 };
50
51 long rc = send_msg(session, &tx_msg);
52 if (rc < 0) {
53 TLOGE("%s: failed (%ld) to send_msg\n", __func__, rc);
54 return rc;
55 }
56
57 if (((size_t)rc) != sizeof(msg)) {
58 TLOGE("%s: msg invalid size (%zu != %zu)", __func__, (size_t)rc,
59 sizeof(msg));
60 return ERR_IO;
61 }
62
63 return NO_ERROR;
64 }
65
await_response(keymaster_session_t session,struct ipc_msg_info * inf)66 static long await_response(keymaster_session_t session,
67 struct ipc_msg_info* inf) {
68 uevent_t uevt;
69 long rc = wait(session, &uevt, INFINITE_TIME);
70 if (rc != NO_ERROR) {
71 TLOGE("%s: interrupted waiting for response (%ld)\n", __func__, rc);
72 return rc;
73 }
74
75 rc = get_msg(session, inf);
76 if (rc != NO_ERROR) {
77 TLOGE("%s: failed to get_msg (%ld)\n", __func__, rc);
78 }
79
80 return rc;
81 }
82
read_response(keymaster_session_t session,uint32_t msg_id,uint32_t cmd,uint8_t * buf,uint32_t size)83 static long read_response(keymaster_session_t session,
84 uint32_t msg_id,
85 uint32_t cmd,
86 uint8_t* buf,
87 uint32_t size) {
88 struct keymaster_message msg;
89
90 struct iovec rx_iov[2] = {
91 {.iov_base = &msg, .iov_len = sizeof(msg)},
92 {.iov_base = buf, .iov_len = size},
93 };
94 struct ipc_msg rx_msg = {
95 .iov = rx_iov,
96 .num_iov = 2,
97 };
98
99 long rc = read_msg(session, msg_id, 0, &rx_msg);
100 put_msg(session, msg_id);
101
102 if ((cmd | KM_RESP_BIT) != (msg.cmd & ~(KM_STOP_BIT))) {
103 TLOGE("%s: invalid response (0x%x) for cmd (0x%x)\n", __func__, msg.cmd,
104 cmd);
105 return ERR_NOT_VALID;
106 }
107
108 return rc;
109 }
110
keymaster_open(void)111 int keymaster_open(void) {
112 return connect(KEYMASTER_SECURE_PORT, IPC_CONNECT_WAIT_FOR_PORT);
113 }
114
keymaster_close(keymaster_session_t session)115 void keymaster_close(keymaster_session_t session) {
116 close(session);
117 }
118
keymaster_send_command(keymaster_session_t session,uint8_t command,uint8_t ** data_buf_p,uint32_t * size_p)119 int keymaster_send_command(keymaster_session_t session,
120 uint8_t command,
121 uint8_t** data_buf_p,
122 uint32_t* size_p) {
123 if (size_p == NULL || data_buf_p == NULL) {
124 return ERR_NOT_VALID;
125 }
126
127 long rc = send_req(session, command);
128 if (rc < 0) {
129 TLOGE("%s: failed (%ld) to send req\n", __func__, rc);
130 return rc;
131 }
132
133 struct ipc_msg_info inf;
134 rc = await_response(session, &inf);
135 if (rc < 0) {
136 TLOGE("%s: failed (%ld) to await response\n", __func__, rc);
137 return rc;
138 }
139
140 if (inf.len <= sizeof(struct keymaster_message)) {
141 TLOGE("%s: invalid response len (%zu)\n", __func__, inf.len);
142 put_msg(session, inf.id);
143 return ERR_NOT_FOUND;
144 }
145
146 size_t size = inf.len - sizeof(struct keymaster_message);
147 uint8_t* data_buf = malloc(size);
148 if (data_buf == NULL) {
149 TLOGE("%s: out of memory (%zu)\n", __func__, inf.len);
150 put_msg(session, inf.id);
151 return ERR_NO_MEMORY;
152 }
153
154 rc = read_response(session, inf.id, command, data_buf, size);
155 if (rc < 0) {
156 goto err_bad_read;
157 }
158
159 size_t read_len = (size_t)rc;
160 if (read_len != inf.len) {
161 // data read in does not match message length
162 TLOGE("%s: invalid read length: (%zu != %zu)\n", __func__, read_len,
163 inf.len);
164 rc = ERR_IO;
165 goto err_bad_read;
166 }
167
168 *size_p = (uint32_t)size;
169 *data_buf_p = data_buf;
170 return NO_ERROR;
171
172 err_bad_read:
173 free(data_buf);
174 TLOGE("%s: failed read_msg (%ld)\n", __func__, rc);
175 return rc;
176 }
177
keymaster_get_auth_token_key(keymaster_session_t session,uint8_t ** key_buf_p,uint32_t * size_p)178 int keymaster_get_auth_token_key(keymaster_session_t session,
179 uint8_t** key_buf_p,
180 uint32_t* size_p) {
181 long rc = keymaster_send_command(session, KM_GET_AUTH_TOKEN_KEY, key_buf_p,
182 size_p);
183 /*
184 * TODO: Return message of this API contains an error if one happened and a
185 * key on success. It may be impossible to distinguish the two if they are
186 * the same size. A proper fix would require changing the layout of the
187 * return message. However, that changes the ABI. So, just assume that the
188 * key is 32 bytes. We know that from KM code.
189 */
190 if (rc == NO_ERROR && *size_p != AUTH_TOKEN_KEY_LEN) {
191 TLOGE("%s: auth token key wrong length: %u, expected %d\n", __func__,
192 *size_p, AUTH_TOKEN_KEY_LEN);
193 rc = ERR_BAD_LEN;
194 free(*key_buf_p);
195 *key_buf_p = NULL;
196 }
197 return rc;
198 }
199
keymaster_get_device_info(keymaster_session_t session,uint8_t ** info_buffer_p,uint32_t * size_p)200 int keymaster_get_device_info(keymaster_session_t session,
201 uint8_t** info_buffer_p,
202 uint32_t* size_p) {
203 long rc = keymaster_send_command(session, KM_GET_DEVICE_INFO, info_buffer_p,
204 size_p);
205 /*
206 * TODO: Return message of this API contains an error if one happened and a
207 * key on success. It may be impossible to distinguish the two if they are
208 * the same size. A proper fix would require changing the layout of the
209 * return message. However, that changes the ABI. So, attempt to parse the
210 * message as a valid CBOR map with non-zero entries. If this fails, it's
211 * an error.
212 */
213 if (rc == NO_ERROR) {
214 struct CborIn in;
215 CborInInit(*info_buffer_p, *size_p, &in);
216 size_t pair_count;
217 if (*size_p == 0 ||
218 CborReadMap(&in, &pair_count) != CBOR_READ_RESULT_OK) {
219 TLOGE("%s: device info byte stream is not valid CBOR or a map.\n",
220 __func__);
221 goto err_bad_cbor;
222 }
223 // Each entry would require at least two bytes.
224 if (*size_p < pair_count * 2) {
225 TLOGE("%s: Device info is malformed. Size is %u, expected > %zu\n",
226 __func__, *size_p, pair_count * 2);
227 goto err_bad_cbor;
228 }
229 }
230 return rc;
231
232 err_bad_cbor:
233 rc = ERR_FAULT;
234 free(*info_buffer_p);
235 *info_buffer_p = NULL;
236 return rc;
237 }
238
keymaster_get_uds_certs(keymaster_session_t session,uint8_t ** cert_buffer_p,uint32_t * size_p)239 int keymaster_get_uds_certs(keymaster_session_t session,
240 uint8_t** cert_buffer_p,
241 uint32_t* size_p) {
242 uint8_t* data = NULL;
243 uint32_t data_len = 0;
244 long rc =
245 keymaster_send_command(session, KM_GET_UDS_CERTS, &data, &data_len);
246 if (rc != NO_ERROR) {
247 return rc;
248 }
249
250 // The first four bytes (native endian) after the (consumed) command code
251 // indicate the error code for the command (0 for success).
252 if (data_len < sizeof(uint32_t)) {
253 TLOGE("%s: UDS certs return code wrong length: %zu, expected >= %zu\n",
254 __func__, (size_t)data_len, sizeof(uint32_t));
255 rc = ERR_BAD_LEN;
256 goto exit;
257 }
258 uint32_t errcode = *(uint32_t*)data;
259 if (errcode != 0) {
260 TLOGE("%s: UDS certs retrieval failed: %u\n", __func__, errcode);
261 rc = ERR_FAULT;
262 goto exit;
263 }
264
265 // Remainder of message is the UDS certs, starting with a 32-bit (native
266 // endian) length.
267 uint32_t remaining_len = data_len - sizeof(uint32_t);
268 uint8_t* rest = data + sizeof(uint32_t);
269 if (remaining_len < sizeof(uint32_t)) {
270 TLOGE("%s: UDS cert data wrong length: %zu, expected >= %zu\n",
271 __func__, (size_t)remaining_len, sizeof(uint32_t));
272 rc = ERR_BAD_LEN;
273 goto exit;
274 }
275
276 *size_p = *(uint32_t*)rest;
277 remaining_len -= sizeof(uint32_t);
278 rest += sizeof(uint32_t);
279 if (*size_p != remaining_len) {
280 TLOGE("%s: UDS cert data inconsistent length: claims %zu, %zu remaining\n",
281 __func__, (size_t)(*size_p), (size_t)remaining_len);
282 rc = ERR_BAD_LEN;
283 goto exit;
284 }
285
286 // Allocate space for just the UDS certs.
287 *cert_buffer_p = malloc(*size_p);
288 if (*cert_buffer_p == NULL) {
289 TLOGE("%s: out of memory (%zu)\n", __func__, (size_t)(*size_p));
290 rc = ERR_NO_MEMORY;
291 goto exit;
292 }
293 memcpy(*cert_buffer_p, rest, *size_p);
294
295 exit:
296 // Always free the (prefixed) response buffer.
297 free(data);
298 return rc;
299 }
300
mint_hmac(uint8_t * key,size_t key_size,uint8_t * message,size_t message_size,uint8_t * hmac)301 static int mint_hmac(uint8_t* key,
302 size_t key_size,
303 uint8_t* message,
304 size_t message_size,
305 uint8_t* hmac) {
306 unsigned int tok_size;
307 unsigned char* ret;
308 memset(hmac, 0, HMAC_LEN);
309 ret = HMAC(EVP_sha256(), (void*)key, key_size, message, message_size, hmac,
310 &tok_size);
311 if (ret == NULL || tok_size != HMAC_LEN) {
312 TLOGE("Failed to execute HMAC()!\n");
313 return ERR_FAULT;
314 }
315
316 return NO_ERROR;
317 }
318
keymaster_sign_auth_token(keymaster_session_t session,hw_auth_token_t * token)319 int keymaster_sign_auth_token(keymaster_session_t session,
320 hw_auth_token_t* token) {
321 int ret = NO_ERROR;
322
323 if (token == NULL) {
324 TLOGE("Invalid token!\n");
325 return ERR_NOT_VALID;
326 }
327
328 uint8_t* key_buf;
329 uint32_t key_buf_size;
330 ret = keymaster_get_auth_token_key(session, &key_buf, &key_buf_size);
331 if (ret) {
332 return ret;
333 }
334
335 /* Initialize the token and message size */
336 size_t message_size = sizeof(hw_auth_token_t) - sizeof(token->hmac);
337 /* Mint the token key with the given HMAC key and message */
338 ret = mint_hmac(key_buf, key_buf_size, (uint8_t*)token, message_size,
339 token->hmac);
340
341 free_mem:
342 free(key_buf);
343 return ret;
344 }
345
keymaster_validate_auth_token(keymaster_session_t session,hw_auth_token_t * token)346 int keymaster_validate_auth_token(keymaster_session_t session,
347 hw_auth_token_t* token) {
348 int ret = NO_ERROR;
349
350 if (token == NULL) {
351 TLOGE("Invalid token!\n");
352 return ERR_NOT_VALID;
353 }
354
355 uint8_t* key_buf;
356 uint32_t key_buf_size;
357 ret = keymaster_get_auth_token_key(session, &key_buf, &key_buf_size);
358 if (ret) {
359 return ret;
360 }
361
362 /* compute the expected token hmac */
363 uint8_t expected_hmac[HMAC_LEN];
364 size_t message_size = sizeof(hw_auth_token_t) - sizeof(token->hmac);
365
366 ret = mint_hmac(key_buf, key_buf_size, (uint8_t*)token, message_size,
367 expected_hmac);
368 if (ret) {
369 goto free_mem;
370 }
371
372 /* Compare the expected hmac with the provided hmac */
373 ret = memcmp(expected_hmac, token->hmac, sizeof(expected_hmac));
374
375 free_mem:
376 free(key_buf);
377 return ret;
378 }
379