1 /*
2  * Copyright (C) 2016 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 #define TLOG_TAG "hwkey_srv"
18 
19 #include <assert.h>
20 #include <lk/list.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <uapi/err.h>
27 
28 #include <interface/hwkey/hwkey.h>
29 #include <lib/tipc/tipc.h>
30 #include <openssl/evp.h>
31 #include <openssl/mem.h>
32 #include <trusty_log.h>
33 
34 #include <hwcrypto/hwrng_dev.h>
35 #include <hwcrypto_consts.h>
36 #include "hwkey_srv_priv.h"
37 
38 struct hwkey_chan_ctx {
39     struct tipc_event_handler evt_handler;
40     handle_t chan;
41     uuid_t uuid;
42 };
43 
44 /**
45  * An opaque key access token.
46  *
47  * Clients can retrieve an opaque access token as a handle to a key they are
48  * allowed to use but not read directly. This handle can then be passed to other
49  * crypto services which can use the token to retrieve the actual key from
50  * hwkey.
51  */
52 typedef char access_token_t[HWKEY_OPAQUE_HANDLE_SIZE];
53 
54 struct opaque_handle_node {
55     const struct hwkey_keyslot* key_slot;
56     struct hwkey_chan_ctx* owner;
57     access_token_t token;
58     struct list_node node;
59 };
60 
61 /*
62  * Global list of currently valid opaque handles. Each client may only have a
63  * single entry in this list for a given key slot, and this entry will be
64  * cleaned up when the connection it was created for is closed.
65  */
66 static struct list_node opaque_handles = LIST_INITIAL_VALUE(opaque_handles);
67 
68 static void hwkey_port_handler(const uevent_t* ev, void* priv);
69 static void hwkey_chan_handler(const uevent_t* ev, void* priv);
70 
71 static struct tipc_event_handler hwkey_port_evt_handler = {
72         .proc = hwkey_port_handler,
73 };
74 
75 static uint8_t req_data[HWKEY_MAX_MSG_SIZE + 1];
76 static __attribute__((aligned(4))) uint8_t key_data[HWKEY_MAX_MSG_SIZE];
77 
78 static unsigned int key_slot_cnt;
79 static const struct hwkey_keyslot* key_slots;
80 
is_opaque_handle(const struct hwkey_keyslot * key_slot)81 static bool is_opaque_handle(const struct hwkey_keyslot* key_slot) {
82     assert(key_slot);
83     return key_slot->handler == get_key_handle;
84 }
85 
delete_opaque_handle(struct opaque_handle_node * node)86 static void delete_opaque_handle(struct opaque_handle_node* node) {
87     assert(node);
88 
89     /* Zero out the access token just in case the memory is reused */
90     memset(node->token, 0, HWKEY_OPAQUE_HANDLE_SIZE);
91 
92     list_delete(&node->node);
93     free(node);
94 }
95 
96 /*
97  * Close specified hwkey context
98  */
hwkey_ctx_close(struct hwkey_chan_ctx * ctx)99 static void hwkey_ctx_close(struct hwkey_chan_ctx* ctx) {
100     struct opaque_handle_node* entry;
101     struct opaque_handle_node* temp;
102     list_for_every_entry_safe(&opaque_handles, entry, temp,
103                               struct opaque_handle_node, node) {
104         if (entry->owner == ctx) {
105             delete_opaque_handle(entry);
106         }
107     }
108     close(ctx->chan);
109     free(ctx);
110 }
111 
112 /*
113  * Send response message
114  */
hwkey_send_rsp(struct hwkey_chan_ctx * ctx,struct hwkey_msg * rsp_hdr,uint8_t * rsp_data,size_t rsp_data_len)115 static int hwkey_send_rsp(struct hwkey_chan_ctx* ctx,
116                           struct hwkey_msg* rsp_hdr,
117                           uint8_t* rsp_data,
118                           size_t rsp_data_len) {
119     rsp_hdr->header.cmd |= HWKEY_RESP_BIT;
120     return tipc_send2(ctx->chan, rsp_hdr, sizeof(*rsp_hdr), rsp_data,
121                       rsp_data_len);
122 }
123 
is_allowed_to_read_opaque_key(const uuid_t * uuid,const struct hwkey_keyslot * slot)124 static bool is_allowed_to_read_opaque_key(const uuid_t* uuid,
125                                           const struct hwkey_keyslot* slot) {
126     assert(slot);
127     const struct hwkey_opaque_handle_data* handle = slot->priv;
128     assert(handle);
129 
130     for (size_t i = 0; i < handle->allowed_uuids_len; ++i) {
131         if (memcmp(handle->allowed_uuids[i], uuid, sizeof(uuid_t)) == 0) {
132             return true;
133         }
134     }
135     return false;
136 }
137 
find_opaque_handle_for_slot(const struct hwkey_keyslot * slot)138 static struct opaque_handle_node* find_opaque_handle_for_slot(
139         const struct hwkey_keyslot* slot) {
140     struct opaque_handle_node* entry;
141     list_for_every_entry(&opaque_handles, entry, struct opaque_handle_node,
142                          node) {
143         if (entry->key_slot == slot) {
144             return entry;
145         }
146     }
147 
148     return NULL;
149 }
150 
151 /*
152  * If a handle doesn't exist yet for the given slot, create and insert a new one
153  * in the global list.
154  */
insert_handle_node(struct hwkey_chan_ctx * ctx,const struct hwkey_keyslot * slot)155 static uint32_t insert_handle_node(struct hwkey_chan_ctx* ctx,
156                                    const struct hwkey_keyslot* slot) {
157     struct opaque_handle_node* entry = find_opaque_handle_for_slot(slot);
158 
159     if (!entry) {
160         entry = calloc(1, sizeof(struct opaque_handle_node));
161         if (!entry) {
162             TLOGE("Could not allocate new opaque_handle_node\n");
163             return HWKEY_ERR_GENERIC;
164         }
165 
166         entry->owner = ctx;
167         entry->key_slot = slot;
168         list_add_tail(&opaque_handles, &entry->node);
169     }
170 
171     return HWKEY_NO_ERROR;
172 }
173 
_handle_slots(struct hwkey_chan_ctx * ctx,const char * slot_id,const struct hwkey_keyslot * slots,unsigned int slot_cnt,uint8_t * kbuf,size_t kbuf_len,size_t * klen)174 static uint32_t _handle_slots(struct hwkey_chan_ctx* ctx,
175                               const char* slot_id,
176                               const struct hwkey_keyslot* slots,
177                               unsigned int slot_cnt,
178                               uint8_t* kbuf,
179                               size_t kbuf_len,
180                               size_t* klen) {
181     if (!slots)
182         return HWKEY_ERR_NOT_FOUND;
183 
184     for (unsigned int i = 0; i < slot_cnt; i++, slots++) {
185         /* check key id */
186         if (strcmp(slots->key_id, slot_id))
187             continue;
188 
189         /* Check if the caller is allowed to get that key */
190         if (memcmp(&ctx->uuid, slots->uuid, sizeof(uuid_t)) == 0) {
191             if (slots->handler) {
192                 if (is_opaque_handle(slots)) {
193                     uint32_t rc = insert_handle_node(ctx, slots);
194                     if (rc != HWKEY_NO_ERROR)
195                         return rc;
196                 }
197                 return slots->handler(slots, kbuf, kbuf_len, klen);
198             }
199         }
200     }
201 
202     /*
203      * We couldn't match a key ID, so try to treat the id as an opaque access
204      * handle
205      */
206     return get_opaque_key(&ctx->uuid, slot_id, kbuf, kbuf_len, klen);
207 }
208 
hwkey_get_derived_key(const struct hwkey_derived_keyslot_data * data,uint8_t * kbuf,size_t kbuf_len,size_t * klen)209 uint32_t hwkey_get_derived_key(const struct hwkey_derived_keyslot_data* data,
210                                uint8_t* kbuf,
211                                size_t kbuf_len,
212                                size_t* klen) {
213     assert(kbuf);
214     assert(klen);
215     assert(data);
216     assert(data->encrypted_key_size_ptr);
217 
218     uint8_t key_buffer[HWKEY_DERIVED_KEY_MAX_SIZE] = {0};
219     size_t key_len;
220     uint32_t rc =
221             data->retriever(data, key_buffer, sizeof(key_buffer), &key_len);
222     if (rc != HWKEY_NO_ERROR) {
223         return rc;
224     }
225 
226     const EVP_CIPHER* cipher;
227     switch (key_len) {
228     case 16:
229         cipher = EVP_aes_128_cbc();
230         break;
231     case 32:
232         cipher = EVP_aes_256_cbc();
233         break;
234     default:
235         TLOGE("invalid key length: (%zd)\n", key_len);
236         return HWKEY_ERR_GENERIC;
237     }
238 
239     int evp_ret;
240     int out_len = 0;
241     uint8_t* iv = NULL;
242     EVP_CIPHER_CTX* cipher_ctx = EVP_CIPHER_CTX_new();
243     if (!cipher_ctx) {
244         return HWKEY_ERR_GENERIC;
245     }
246 
247     /* if we exit early */
248     rc = HWKEY_ERR_GENERIC;
249 
250     evp_ret = EVP_DecryptInit_ex(cipher_ctx, cipher, NULL, NULL, NULL);
251     if (evp_ret != 1) {
252         TLOGE("Initializing decryption algorithm failed\n");
253         goto out;
254     }
255 
256     unsigned int iv_length = EVP_CIPHER_CTX_iv_length(cipher_ctx);
257 
258     /* encrypted key contains IV + ciphertext */
259     if (iv_length >= *data->encrypted_key_size_ptr) {
260         TLOGE("Encrypted key is too small\n");
261         goto out;
262     }
263 
264     if (kbuf_len < *data->encrypted_key_size_ptr - iv_length) {
265         TLOGE("Not enough space in output buffer\n");
266         rc = HWKEY_ERR_BAD_LEN;
267         goto out;
268     }
269 
270     evp_ret = EVP_DecryptInit_ex(cipher_ctx, cipher, NULL, key_buffer,
271                                  data->encrypted_key_data);
272     if (evp_ret != 1) {
273         TLOGE("Initializing decryption algorithm failed\n");
274         goto out;
275     }
276 
277     evp_ret = EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
278     if (evp_ret != 1) {
279         TLOGE("EVP_CIPHER_CTX_set_padding failed\n");
280         goto out;
281     }
282 
283     evp_ret = EVP_DecryptUpdate(cipher_ctx, kbuf, &out_len,
284                                 data->encrypted_key_data + iv_length,
285                                 *data->encrypted_key_size_ptr - iv_length);
286     if (evp_ret != 1) {
287         TLOGE("EVP_DecryptUpdate failed\n");
288         goto out;
289     }
290 
291     /* We don't support padding so input length == output length */
292     assert(out_len >= 0 &&
293            (unsigned int)out_len == *data->encrypted_key_size_ptr - iv_length);
294 
295     evp_ret = EVP_DecryptFinal_ex(cipher_ctx, NULL, &out_len);
296     if (evp_ret != 1) {
297         TLOGE("EVP_DecryptFinal failed\n");
298         goto out;
299     }
300 
301     assert(out_len == 0);
302 
303     *klen = *data->encrypted_key_size_ptr - iv_length;
304 
305     /* Decryption was successful */
306     rc = HWKEY_NO_ERROR;
307 
308 out:
309     if (iv) {
310         free(iv);
311     }
312     EVP_CIPHER_CTX_free(cipher_ctx);
313     return rc;
314 }
315 
316 /*
317  * Handle get key slot command
318  */
hwkey_handle_get_keyslot_cmd(struct hwkey_chan_ctx * ctx,struct hwkey_msg * hdr,const char * slot_id)319 static int hwkey_handle_get_keyslot_cmd(struct hwkey_chan_ctx* ctx,
320                                         struct hwkey_msg* hdr,
321                                         const char* slot_id) {
322     int rc;
323     size_t klen = 0;
324 
325     hdr->header.status = _handle_slots(ctx, slot_id, key_slots, key_slot_cnt,
326                                        key_data, sizeof(key_data), &klen);
327 
328     rc = hwkey_send_rsp(ctx, hdr, key_data, klen);
329     if (klen) {
330         /* sanitize key buffer */
331         memset(key_data, 0, klen);
332     }
333     return rc;
334 }
335 
336 /* Shared implementation for the unversioned key derivation API */
hwkey_handle_derive_key_impl(uint32_t * kdf_version,const uuid_t * uuid,const uint8_t * context,size_t context_len,uint8_t * key,size_t key_len)337 static uint32_t hwkey_handle_derive_key_impl(uint32_t* kdf_version,
338                                              const uuid_t* uuid,
339                                              const uint8_t* context,
340                                              size_t context_len,
341                                              uint8_t* key,
342                                              size_t key_len) {
343     /* check requested key derivation function */
344     if (*kdf_version == HWKEY_KDF_VERSION_BEST) {
345         *kdf_version = HWKEY_KDF_VERSION_1;
346     }
347 
348     if (!context || !key || key_len == 0) {
349         return HWKEY_ERR_NOT_VALID;
350     }
351 
352     switch (*kdf_version) {
353     case HWKEY_KDF_VERSION_1:
354         return derive_key_v1(uuid, context, context_len, key, key_len);
355 
356     default:
357         TLOGE("%u is unsupported KDF function\n", *kdf_version);
358         return HWKEY_ERR_NOT_IMPLEMENTED;
359     }
360 }
361 
362 /*
363  * Handle Derive key cmd
364  */
hwkey_handle_derive_key_cmd(struct hwkey_chan_ctx * ctx,struct hwkey_msg * hdr,const uint8_t * ikm_data,size_t ikm_len)365 static int hwkey_handle_derive_key_cmd(struct hwkey_chan_ctx* ctx,
366                                        struct hwkey_msg* hdr,
367                                        const uint8_t* ikm_data,
368                                        size_t ikm_len) {
369     int rc;
370     size_t key_len = ikm_len;
371     if (key_len > HWKEY_MAX_MSG_SIZE - sizeof(*hdr)) {
372         TLOGE("Key length exceeds message size: %zu\n", key_len);
373         key_len = 0;
374         hdr->header.status = HWKEY_ERR_BAD_LEN;
375         goto send_response;
376     }
377 
378     hdr->header.status = hwkey_handle_derive_key_impl(
379             &hdr->arg1, &ctx->uuid, ikm_data, ikm_len, key_data, key_len);
380 
381 send_response:
382     rc = hwkey_send_rsp(ctx, hdr, key_data, key_len);
383     if (key_len) {
384         /* sanitize key buffer */
385         memset(key_data, 0, sizeof(key_data));
386     }
387     return rc;
388 }
389 
390 /**
391  * hwkey_handle_derive_versioned_key_cmd() - Handle versioned key derivation
392  * @ctx: client context
393  * @msg: request/response message
394  * @context: key derivation info input
395  * @context_len: length in bytes of @context
396  *
397  * Derive a new key from an internal secret key, unique to the provided context,
398  * UUID of the client, and requested rollback version. Rollback versions greater
399  * than the current image or fused rollback version are not allowed. See &struct
400  * hwkey_derive_versioned_msg for more details.
401  *
402  * Because key versions newer than the current image rollback version are not
403  * available to clients, incrementing this version in the Trusty image results
404  * in a new set of keys being available that previous Trusty apps never had
405  * access to. This mechanism can be used to roll to new keys after patching a
406  * Trusty app vulnerability that may have exposed old keys. If the key
407  * derivation is implemented outside of Trusty entirely, then keys can be
408  * refreshed after a potential Trusty kernel compromise.
409  *
410  * Return: A negative return value indicates an error occurred sending the IPC
411  *         response back to the client.
412  */
hwkey_handle_derive_versioned_key_cmd(struct hwkey_chan_ctx * ctx,struct hwkey_derive_versioned_msg * msg,const uint8_t * context,size_t context_len)413 static int hwkey_handle_derive_versioned_key_cmd(
414         struct hwkey_chan_ctx* ctx,
415         struct hwkey_derive_versioned_msg* msg,
416         const uint8_t* context,
417         size_t context_len) {
418     int i;
419     int rc;
420     bool shared = msg->key_options & HWKEY_SHARED_KEY_TYPE;
421     uint32_t status;
422     size_t key_len;
423 
424     key_len = msg->key_len;
425     if (key_len > HWKEY_MAX_MSG_SIZE - sizeof(*msg)) {
426         TLOGE("Key length (%zu) exceeds buffer length\n", key_len);
427         status = HWKEY_ERR_BAD_LEN;
428         goto send_response;
429     }
430 
431     /*
432      * make sure to retrieve the current OS version before calling
433      * hwkey_derive_versioned_msg_compatible_with_unversioned() so that we
434      * derive the same key with CURRENT == 0 and 0 passed explicitly.
435      */
436 
437     int os_rollback_version =
438             msg->rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX];
439     if (os_rollback_version == HWKEY_ROLLBACK_VERSION_CURRENT) {
440         os_rollback_version =
441                 get_current_os_rollback_version(msg->rollback_version_source);
442         if (os_rollback_version < 0) {
443             status = HWKEY_ERR_GENERIC;
444             goto send_response;
445         }
446         msg->rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] =
447                 os_rollback_version;
448     }
449 
450     for (i = HWKEY_ROLLBACK_VERSION_SUPPORTED_COUNT;
451          i < HWKEY_ROLLBACK_VERSION_INDEX_COUNT; ++i) {
452         if (msg->rollback_versions[i] != 0) {
453             TLOGE("Unsupported rollback version set: %d\n", i);
454             status = HWKEY_ERR_NOT_VALID;
455             goto send_response;
456         }
457     }
458 
459     if (hwkey_derive_versioned_msg_compatible_with_unversioned(msg)) {
460         status = hwkey_handle_derive_key_impl(&msg->kdf_version, &ctx->uuid,
461                                               context, context_len, key_data,
462                                               key_len);
463         if (key_len == 0) {
464             /*
465              * derive_key_v1() doesn't support an empty key length, but we still
466              * want to allow querying key versions with NULL key and zero
467              * length. Reset the status to ok in this case.
468              */
469             status = HWKEY_NO_ERROR;
470         }
471         goto send_response;
472     }
473 
474     /* check requested key derivation function */
475     if (msg->kdf_version == HWKEY_KDF_VERSION_BEST) {
476         msg->kdf_version = HWKEY_KDF_VERSION_1;
477     }
478 
479     switch (msg->kdf_version) {
480     case HWKEY_KDF_VERSION_1:
481         status = derive_key_versioned_v1(&ctx->uuid, shared,
482                                          msg->rollback_version_source,
483                                          msg->rollback_versions, context,
484                                          context_len, key_data, key_len);
485         break;
486 
487     default:
488         TLOGE("%u is unsupported KDF function\n", msg->kdf_version);
489         status = HWKEY_ERR_NOT_IMPLEMENTED;
490     }
491 
492 send_response:
493     if (status != HWKEY_NO_ERROR) {
494         msg->key_len = 0;
495     }
496 
497     msg->header.status = status;
498     msg->header.cmd |= HWKEY_RESP_BIT;
499     rc = tipc_send2(ctx->chan, msg, sizeof(*msg), key_data, msg->key_len);
500     if (msg->key_len) {
501         /* sanitize key buffer */
502         memset(key_data, 0, sizeof(key_data));
503     }
504     return rc;
505 }
506 
507 /*
508  *  Read and queue HWKEY request message
509  */
hwkey_chan_handle_msg(struct hwkey_chan_ctx * ctx)510 static int hwkey_chan_handle_msg(struct hwkey_chan_ctx* ctx) {
511     int rc;
512     size_t req_data_len;
513     struct hwkey_msg_header* hdr;
514 
515     rc = tipc_recv1(ctx->chan, sizeof(*hdr), req_data, sizeof(req_data) - 1);
516     if (rc < 0) {
517         TLOGE("failed (%d) to recv msg from chan %d\n", rc, ctx->chan);
518         return rc;
519     }
520 
521     req_data_len = (size_t)rc;
522 
523     if (req_data_len < sizeof(*hdr)) {
524         TLOGE("Received too little data (%zu) from chan %d\n", req_data_len,
525               ctx->chan);
526         return ERR_BAD_LEN;
527     }
528 
529     hdr = (struct hwkey_msg_header*)req_data;
530 
531     /* handle it */
532     switch (hdr->cmd) {
533     case HWKEY_GET_KEYSLOT:
534         req_data[req_data_len] = 0; /* force zero termination */
535         if (req_data_len < sizeof(struct hwkey_msg)) {
536             TLOGE("Received too little data (%zu) from chan %d\n", req_data_len,
537                   ctx->chan);
538             return ERR_BAD_LEN;
539         }
540         rc = hwkey_handle_get_keyslot_cmd(
541                 ctx, (struct hwkey_msg*)req_data,
542                 (const char*)(req_data + sizeof(struct hwkey_msg)));
543         break;
544 
545     case HWKEY_DERIVE:
546         if (req_data_len < sizeof(struct hwkey_msg)) {
547             TLOGE("Received too little data (%zu) from chan %d\n", req_data_len,
548                   ctx->chan);
549             return ERR_BAD_LEN;
550         }
551         rc = hwkey_handle_derive_key_cmd(
552                 ctx, (struct hwkey_msg*)req_data,
553                 req_data + sizeof(struct hwkey_msg),
554                 req_data_len - sizeof(struct hwkey_msg));
555         memset(req_data, 0, req_data_len); /* sanitize request buffer */
556         break;
557 
558     case HWKEY_DERIVE_VERSIONED:
559         if (req_data_len < sizeof(struct hwkey_derive_versioned_msg)) {
560             TLOGE("Received too little data (%zu) from chan %d\n", req_data_len,
561                   ctx->chan);
562             return ERR_BAD_LEN;
563         }
564         rc = hwkey_handle_derive_versioned_key_cmd(
565                 ctx, (struct hwkey_derive_versioned_msg*)req_data,
566                 req_data + sizeof(struct hwkey_derive_versioned_msg),
567                 req_data_len - sizeof(struct hwkey_derive_versioned_msg));
568         memset(req_data, 0, req_data_len); /* sanitize request buffer */
569         break;
570 
571     default:
572         TLOGE("Unsupported request: %d\n", (int)hdr->cmd);
573         hdr->status = HWKEY_ERR_NOT_IMPLEMENTED;
574         hdr->cmd |= HWKEY_RESP_BIT;
575         rc = tipc_send1(ctx->chan, hdr, sizeof(*hdr));
576     }
577 
578     return rc;
579 }
580 
581 /*
582  *  HWKEY service channel event handler
583  */
hwkey_chan_handler(const uevent_t * ev,void * priv)584 static void hwkey_chan_handler(const uevent_t* ev, void* priv) {
585     struct hwkey_chan_ctx* ctx = priv;
586 
587     assert(ctx);
588     assert(ev->handle == ctx->chan);
589 
590     tipc_handle_chan_errors(ev);
591 
592     if (ev->event & IPC_HANDLE_POLL_HUP) {
593         /* closed by peer. */
594         hwkey_ctx_close(ctx);
595         return;
596     }
597 
598     if (ev->event & IPC_HANDLE_POLL_MSG) {
599         int rc = hwkey_chan_handle_msg(ctx);
600         if (rc < 0) {
601             /* report an error and close channel */
602             TLOGE("failed (%d) to handle event on channel %d\n", rc,
603                   ev->handle);
604             hwkey_ctx_close(ctx);
605         }
606     }
607 }
608 
609 /*
610  * HWKEY service port event handler
611  */
hwkey_port_handler(const uevent_t * ev,void * priv)612 static void hwkey_port_handler(const uevent_t* ev, void* priv) {
613     uuid_t peer_uuid;
614 
615     tipc_handle_port_errors(ev);
616 
617     if (ev->event & IPC_HANDLE_POLL_READY) {
618         /* incoming connection: accept it */
619         int rc = accept(ev->handle, &peer_uuid);
620         if (rc < 0) {
621             TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle);
622             return;
623         }
624 
625         handle_t chan = (handle_t)rc;
626         if (!hwkey_client_allowed(&peer_uuid)) {
627             TLOGE("access to hwkey service denied\n");
628             close(chan);
629             return;
630         }
631 
632         struct hwkey_chan_ctx* ctx = calloc(1, sizeof(*ctx));
633         if (!ctx) {
634             TLOGE("failed (%d) to allocate context on chan %d\n", rc, chan);
635             close(chan);
636             return;
637         }
638 
639         /* init channel state */
640         ctx->evt_handler.priv = ctx;
641         ctx->evt_handler.proc = hwkey_chan_handler;
642         ctx->chan = chan;
643         ctx->uuid = peer_uuid;
644 
645         rc = set_cookie(chan, &ctx->evt_handler);
646         if (rc < 0) {
647             TLOGE("failed (%d) to set_cookie on chan %d\n", rc, chan);
648             hwkey_ctx_close(ctx);
649             return;
650         }
651     }
652 }
653 
654 /*
655  *  Install Key slot provider
656  */
hwkey_install_keys(const struct hwkey_keyslot * keys,unsigned int kcnt)657 void hwkey_install_keys(const struct hwkey_keyslot* keys, unsigned int kcnt) {
658     assert(key_slots == NULL);
659     assert(key_slot_cnt == 0);
660     assert(keys && kcnt);
661 
662     key_slots = keys;
663     key_slot_cnt = kcnt;
664 }
665 
is_empty_token(const char * access_token)666 static bool is_empty_token(const char* access_token) {
667     for (int i = 0; i < HWKEY_OPAQUE_HANDLE_SIZE; i++) {
668         if (access_token[i] != 0) {
669             assert(strnlen(access_token, HWKEY_OPAQUE_HANDLE_SIZE) ==
670                    HWKEY_OPAQUE_HANDLE_SIZE - 1);
671             return false;
672         }
673     }
674     return true;
675 }
676 
get_key_handle(const struct hwkey_keyslot * slot,uint8_t * kbuf,size_t kbuf_len,size_t * klen)677 uint32_t get_key_handle(const struct hwkey_keyslot* slot,
678                         uint8_t* kbuf,
679                         size_t kbuf_len,
680                         size_t* klen) {
681     assert(kbuf);
682     assert(klen);
683 
684     const struct hwkey_opaque_handle_data* handle = slot->priv;
685     assert(handle);
686     assert(kbuf_len >= HWKEY_OPAQUE_HANDLE_SIZE);
687 
688     struct opaque_handle_node* entry = find_opaque_handle_for_slot(slot);
689     /* _handle_slots should have already created an entry for this slot */
690     assert(entry);
691 
692     if (!is_empty_token(entry->token)) {
693         /*
694          * We do not allow fetching a token again for the same slot again after
695          * the token is first created and returned
696          */
697         return HWKEY_ERR_ALREADY_EXISTS;
698     }
699 
700     /*
701      * We want to generate a null-terminated opaque handle with no interior null
702      * bytes, so we generate extra randomness and only use the non-zero bytes.
703      */
704     uint8_t random_buf[HWKEY_OPAQUE_HANDLE_SIZE + 2];
705     while (1) {
706         int rc = hwrng_dev_get_rng_data(random_buf, sizeof(random_buf));
707         if (rc != NO_ERROR) {
708             /* Don't leave an empty entry if we couldn't generate a token */
709             delete_opaque_handle(entry);
710             return rc;
711         }
712 
713         size_t token_offset = 0;
714         for (size_t i = 0; i < sizeof(random_buf) &&
715                            token_offset < HWKEY_OPAQUE_HANDLE_SIZE - 1;
716              ++i) {
717             if (random_buf[i] != 0) {
718                 entry->token[token_offset] = random_buf[i];
719                 token_offset++;
720             }
721         }
722         if (token_offset == HWKEY_OPAQUE_HANDLE_SIZE - 1) {
723             break;
724         }
725     }
726 
727     /* ensure that token is properly null-terminated */
728     assert(entry->token[HWKEY_OPAQUE_HANDLE_SIZE - 1] == 0);
729 
730     memcpy(kbuf, entry->token, HWKEY_OPAQUE_HANDLE_SIZE);
731     *klen = HWKEY_OPAQUE_HANDLE_SIZE;
732 
733     return HWKEY_NO_ERROR;
734 }
735 
get_opaque_key(const uuid_t * uuid,const char * access_token,uint8_t * kbuf,size_t kbuf_len,size_t * klen)736 uint32_t get_opaque_key(const uuid_t* uuid,
737                         const char* access_token,
738                         uint8_t* kbuf,
739                         size_t kbuf_len,
740                         size_t* klen) {
741     struct opaque_handle_node* entry;
742     list_for_every_entry(&opaque_handles, entry, struct opaque_handle_node,
743                          node) {
744         /* get_key_handle should never leave an empty token in the list */
745         assert(!is_empty_token(entry->token));
746 
747         if (!is_allowed_to_read_opaque_key(uuid, entry->key_slot))
748             continue;
749 
750         /*
751          * We are using a constant-time memcmp here to avoid side-channel
752          * leakage of the access token. Even if we trust the service that is
753          * allowed to retrieve this key, one of its clients may be trying to
754          * brute force the token, so this comparison must be constant-time.
755          */
756         if (CRYPTO_memcmp(entry->token, access_token,
757                           HWKEY_OPAQUE_HANDLE_SIZE) == 0) {
758             const struct hwkey_opaque_handle_data* handle =
759                     entry->key_slot->priv;
760             assert(handle);
761             return handle->retriever(handle, kbuf, kbuf_len, klen);
762         }
763     }
764 
765     return HWKEY_ERR_NOT_FOUND;
766 }
767 
768 /*
769  *  Initialize HWKEY service
770  */
hwkey_start_service(void)771 int hwkey_start_service(void) {
772     int rc;
773     handle_t port;
774 
775     TLOGD("Start HWKEY service\n");
776 
777     /* Initialize service */
778     rc = port_create(HWKEY_PORT, 1, HWKEY_MAX_MSG_SIZE,
779                      IPC_PORT_ALLOW_TA_CONNECT);
780     if (rc < 0) {
781         TLOGE("Failed (%d) to create port %s\n", rc, HWKEY_PORT);
782         return rc;
783     }
784 
785     port = (handle_t)rc;
786     rc = set_cookie(port, &hwkey_port_evt_handler);
787     if (rc) {
788         TLOGE("failed (%d) to set_cookie on port %d\n", rc, port);
789         close(port);
790         return rc;
791     }
792 
793     return NO_ERROR;
794 }
795