1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include <trusty/avb.h>
26 #include <trusty/rpmb.h>
27 #include <trusty/trusty_ipc.h>
28 #include <trusty/util.h>
29 
30 #define LOCAL_LOG 0
31 
32 static bool initialized;
33 static int avb_tipc_version = 1;
34 static struct trusty_ipc_chan avb_chan;
35 
avb_send_request(struct avb_message * msg,void * req,size_t req_len)36 static int avb_send_request(struct avb_message* msg,
37                             void* req,
38                             size_t req_len) {
39     struct trusty_ipc_iovec req_iovs[2] = {
40             {.base = msg, .len = sizeof(*msg)},
41             {.base = req, .len = req_len},
42     };
43 
44     return trusty_ipc_send(&avb_chan, req_iovs, req ? 2 : 1, true);
45 }
46 
avb_read_response(struct avb_message * msg,uint32_t cmd,void * resp,size_t resp_len)47 static int avb_read_response(struct avb_message* msg,
48                              uint32_t cmd,
49                              void* resp,
50                              size_t resp_len) {
51     int rc;
52     struct trusty_ipc_iovec resp_iovs[2] = {
53             {.base = msg, .len = sizeof(*msg)},
54             {.base = resp, .len = resp_len},
55     };
56 
57     rc = trusty_ipc_recv(&avb_chan, resp_iovs, resp ? 2 : 1, true);
58     if (rc < 0) {
59         trusty_error("failed (%d) to recv response\n", rc);
60         return rc;
61     }
62     if (msg->cmd != (cmd | AVB_RESP_BIT)) {
63         trusty_error("malformed response\n");
64         return TRUSTY_ERR_GENERIC;
65     }
66     /* return payload size */
67     return rc - sizeof(*msg);
68 }
69 
70 /*
71  * Convenience function to send a request to the AVB service and read the
72  * response.
73  *
74  * @cmd: the command
75  * @req: the request buffer
76  * @req_size: size of the request buffer
77  * @resp: the response buffer
78  * @resp_size_p: pointer to the size of the response buffer. changed to the
79                  actual size of the response read from the secure side
80  */
avb_do_tipc(uint32_t cmd,void * req,uint32_t req_size,void * resp,uint32_t * resp_size_p)81 static int avb_do_tipc(uint32_t cmd,
82                        void* req,
83                        uint32_t req_size,
84                        void* resp,
85                        uint32_t* resp_size_p) {
86     int rc;
87     struct avb_message msg = {.cmd = cmd};
88 
89     if (!initialized && cmd != AVB_GET_VERSION) {
90         trusty_error("%s: AVB TIPC client not initialized\n", __func__);
91         return TRUSTY_ERR_GENERIC;
92     }
93 
94     rc = avb_send_request(&msg, req, req_size);
95     if (rc < 0) {
96         trusty_error("%s: failed (%d) to send AVB request\n", __func__, rc);
97         return rc;
98     }
99 
100     uint32_t resp_size = resp_size_p ? *resp_size_p : 0;
101     rc = avb_read_response(&msg, cmd, resp, resp_size);
102     if (rc < 0) {
103         trusty_error("%s: failed (%d) to read AVB response\n", __func__, rc);
104         return rc;
105     }
106     /* change response size to actual response size */
107     if (resp_size_p && rc != *resp_size_p) {
108         *resp_size_p = rc;
109     }
110     if (msg.result != AVB_ERROR_NONE) {
111         trusty_error("%s: AVB service returned error (%d)\n", __func__,
112                      msg.result);
113         return TRUSTY_ERR_GENERIC;
114     }
115     return TRUSTY_ERR_NONE;
116 }
117 
avb_get_version(uint32_t * version)118 static int avb_get_version(uint32_t* version) {
119     int rc;
120     struct avb_get_version_resp resp;
121     uint32_t resp_size = sizeof(resp);
122 
123     rc = avb_do_tipc(AVB_GET_VERSION, NULL, 0, &resp, &resp_size);
124 
125     *version = resp.version;
126     return rc;
127 }
128 
avb_tipc_init(struct trusty_ipc_dev * dev)129 int avb_tipc_init(struct trusty_ipc_dev* dev) {
130     int rc;
131     uint32_t version = 0;
132 
133     trusty_assert(dev);
134     trusty_assert(!initialized);
135 
136     trusty_ipc_chan_init(&avb_chan, dev);
137     trusty_debug("Connecting to AVB service\n");
138 
139     /* connect to AVB service and wait for connect to complete */
140     rc = trusty_ipc_connect(&avb_chan, AVB_PORT, true);
141     if (rc < 0) {
142         trusty_error("failed (%d) to connect to '%s'\n", rc, AVB_PORT);
143         return rc;
144     }
145 
146     /* check for version mismatch */
147     rc = avb_get_version(&version);
148     if (rc != 0) {
149         trusty_error("Error getting version");
150         return TRUSTY_ERR_GENERIC;
151     }
152     if (version != avb_tipc_version) {
153         trusty_error("AVB TIPC version mismatch. Expected %u, received %u\n",
154                      avb_tipc_version, version);
155         return TRUSTY_ERR_GENERIC;
156     }
157 
158     /* mark as initialized */
159     initialized = true;
160 
161     return TRUSTY_ERR_NONE;
162 }
163 
avb_tipc_shutdown(struct trusty_ipc_dev * dev)164 void avb_tipc_shutdown(struct trusty_ipc_dev* dev) {
165     if (!initialized)
166         return; /* nothing to do */
167 
168     /* close channel */
169     trusty_ipc_close(&avb_chan);
170 
171     initialized = false;
172 }
173 
trusty_read_rollback_index(uint32_t slot,uint64_t * value)174 int trusty_read_rollback_index(uint32_t slot, uint64_t* value) {
175     int rc;
176     struct avb_rollback_req req = {.slot = slot, .value = 0};
177     struct avb_rollback_resp resp;
178     uint32_t resp_size = sizeof(resp);
179 
180     rc = avb_do_tipc(READ_ROLLBACK_INDEX, &req, sizeof(req), &resp, &resp_size);
181 
182     *value = resp.value;
183     return rc;
184 }
185 
trusty_write_rollback_index(uint32_t slot,uint64_t value)186 int trusty_write_rollback_index(uint32_t slot, uint64_t value) {
187     int rc;
188     struct avb_rollback_req req = {.slot = slot, .value = value};
189     struct avb_rollback_resp resp;
190     uint32_t resp_size = sizeof(resp);
191 
192     rc = avb_do_tipc(WRITE_ROLLBACK_INDEX, &req, sizeof(req), &resp,
193                      &resp_size);
194     return rc;
195 }
196 
trusty_read_permanent_attributes(uint8_t * attributes,uint32_t size)197 int trusty_read_permanent_attributes(uint8_t* attributes, uint32_t size) {
198     uint8_t resp_buf[AVB_MAX_BUFFER_LENGTH];
199     uint32_t resp_size = AVB_MAX_BUFFER_LENGTH;
200     int rc = avb_do_tipc(READ_PERMANENT_ATTRIBUTES, NULL, 0, resp_buf,
201                          &resp_size);
202     if (rc != 0) {
203         return rc;
204     }
205     /* ensure caller passed size matches size returned by Trusty */
206     if (size != resp_size) {
207         return TRUSTY_ERR_INVALID_ARGS;
208     }
209     trusty_memcpy(attributes, resp_buf, resp_size);
210     return rc;
211 }
212 
trusty_write_permanent_attributes(uint8_t * attributes,uint32_t size)213 int trusty_write_permanent_attributes(uint8_t* attributes, uint32_t size) {
214     return avb_do_tipc(WRITE_PERMANENT_ATTRIBUTES, attributes, size, NULL,
215                        NULL);
216 }
217 
trusty_read_lock_state(uint8_t * lock_state)218 int trusty_read_lock_state(uint8_t* lock_state) {
219     uint32_t resp_size = sizeof(*lock_state);
220     return avb_do_tipc(READ_LOCK_STATE, NULL, 0, lock_state, &resp_size);
221 }
222 
trusty_write_lock_state(uint8_t lock_state)223 int trusty_write_lock_state(uint8_t lock_state) {
224     return avb_do_tipc(WRITE_LOCK_STATE, &lock_state, sizeof(lock_state), NULL,
225                        NULL);
226 }
227 
trusty_lock_boot_state(void)228 int trusty_lock_boot_state(void) {
229     return avb_do_tipc(LOCK_BOOT_STATE, NULL, 0, NULL, NULL);
230 }
231