1 /*
2  * Copyright (C) 2020 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 <lib/hwwsk/client.h>
18 
19 #include <assert.h>
20 #include <lib/tipc/tipc.h>
21 #include <lk/macros.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <sys/mman.h>
26 #include <uapi/err.h>
27 
28 #define TLOG_LVL TLOG_LVL_INFO
29 #define TLOG_TAG "hwwsk-client"
30 #include <trusty_log.h>
31 
32 /*
33  * Helper to convert error codes
34  */
hwwsk_err_to_lk_err(uint32_t err)35 static int hwwsk_err_to_lk_err(uint32_t err) {
36     switch (err) {
37     case HWWSK_NO_ERROR:
38         return NO_ERROR;
39 
40     case HWWSK_ERR_GENERIC:
41         return ERR_GENERIC;
42 
43     case HWWSK_ERR_INVALID_ARGS:
44         return ERR_INVALID_ARGS;
45 
46     case HWWSK_ERR_BAD_LEN:
47         return ERR_BAD_LEN;
48 
49     case HWWSK_ERR_NOT_SUPPORTED:
50         return ERR_NOT_SUPPORTED;
51 
52     default:
53         return ERR_GENERIC;
54     }
55 }
56 
handle_reply(handle_t chan,void * buf,size_t buf_size)57 static int handle_reply(handle_t chan, void* buf, size_t buf_size) {
58     int rc;
59     struct uevent evt;
60     struct hwwsk_rsp_hdr rsp;
61 
62     /* wait for reply */
63     wait(chan, &evt, INFINITE_TIME);
64 
65     /* read reply */
66     rc = tipc_recv2(chan, sizeof(rsp), &rsp, sizeof(rsp), buf, buf_size);
67     if (rc < 0) {
68         TLOGD("Failed (%d) to read reply\n", rc);
69         return rc;
70     }
71 
72     /* check server reply */
73     if (rsp.status != 0) {
74         rc = hwwsk_err_to_lk_err(rsp.status);
75         TLOGD("Server returned error (%d)\n", rc);
76         return rc;
77     }
78 
79     if (((size_t)rc - sizeof(rsp)) > buf_size) {
80         TLOGD("buffer too small (%d)\n", rc);
81         return ERR_INVALID_ARGS;
82     }
83 
84     return (size_t)rc - sizeof(rsp);
85 }
86 
hwwsk_generate_key(handle_t hchan,void * buf,size_t buf_sz,uint32_t key_size,uint32_t key_flags,const void * raw_key,size_t raw_key_len)87 int hwwsk_generate_key(handle_t hchan,
88                        void* buf,
89                        size_t buf_sz,
90                        uint32_t key_size,
91                        uint32_t key_flags,
92                        const void* raw_key,
93                        size_t raw_key_len) {
94     int rc;
95     struct {
96         struct hwwsk_req_hdr hdr;
97         struct hwwsk_generate_key_req req;
98     } msg;
99 
100     /* fill request  */
101     memset(&msg, 0, sizeof(msg));
102     msg.hdr.cmd = HWWSK_CMD_GENERATE_KEY;
103     msg.hdr.flags = 0;
104 
105     msg.req.key_size = key_size;
106     msg.req.key_flags = key_flags;
107 
108     /* send request */
109     rc = tipc_send2(hchan, &msg, sizeof(msg), raw_key, raw_key_len);
110     if (rc < 0) {
111         TLOGE("Failed (%d) send request\n", rc);
112         return rc;
113     }
114 
115     return handle_reply(hchan, buf, buf_sz);
116 }
117 
hwwsk_export_key(handle_t hchan,void * buf,size_t buf_sz,const void * key_blob,size_t key_blob_len)118 int hwwsk_export_key(handle_t hchan,
119                      void* buf,
120                      size_t buf_sz,
121                      const void* key_blob,
122                      size_t key_blob_len) {
123     int rc;
124     struct {
125         struct hwwsk_req_hdr hdr;
126     } msg;
127 
128     /* fill request header */
129     msg.hdr.cmd = HWWSK_CMD_EXPORT_KEY;
130     msg.hdr.flags = 0;
131 
132     /* send request */
133     rc = tipc_send2(hchan, &msg, sizeof(msg), key_blob, key_blob_len);
134     if (rc < 0) {
135         TLOGE("Failed (%d) send request\n", rc);
136         return rc;
137     }
138 
139     return handle_reply(hchan, buf, buf_sz);
140 }
141