1 /*
2 * Copyright (C) 2021 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 <trusty/hwbcc.h>
18 #include <trusty/trusty_ipc.h>
19 #include <trusty/util.h>
20
21 #include <uapi/uapi/err.h>
22
23 static struct trusty_ipc_chan hwbcc_chan;
24 static bool initialized;
25
26 #ifndef MIN
27 #define MIN(a, b) ((a) < (b) ? (a) : (b))
28 #endif
29
hwbcc_tipc_init(struct trusty_ipc_dev * dev)30 int hwbcc_tipc_init(struct trusty_ipc_dev* dev) {
31 trusty_assert(dev);
32 trusty_ipc_chan_init(&hwbcc_chan, dev);
33
34 trusty_debug("In hwbcc_tipc_init: connecting to hwbcc service.\n");
35 int rc = trusty_ipc_connect(&hwbcc_chan, HWBCC_PORT, true /*wait*/);
36 if (rc < 0) {
37 trusty_error("In hwbcc_tipc_init:: failed (%d) to connect to '%s'.\n",
38 rc, HWBCC_PORT);
39 return rc;
40 }
41 initialized = true;
42 return TRUSTY_ERR_NONE;
43 }
44
hwbcc_tipc_shutdown(void)45 void hwbcc_tipc_shutdown(void) {
46 if (!initialized) {
47 return;
48 }
49 trusty_ipc_close(&hwbcc_chan);
50 initialized = false;
51 }
52
send_header_only_request(struct hwbcc_req_hdr * hdr,size_t hdr_size)53 static int send_header_only_request(struct hwbcc_req_hdr* hdr,
54 size_t hdr_size) {
55 int num_iovec = 1;
56 struct trusty_ipc_iovec req_iov = {.base = hdr, .len = hdr_size};
57 return trusty_ipc_send(&hwbcc_chan, &req_iov, num_iovec, true);
58 }
59
read_response_with_data(struct hwbcc_req_hdr * hdr,uint8_t * buf,size_t buf_size,size_t * out_size)60 static int read_response_with_data(struct hwbcc_req_hdr* hdr,
61 uint8_t* buf,
62 size_t buf_size,
63 size_t* out_size) {
64 struct hwbcc_resp_hdr resp_hdr = {};
65
66 trusty_assert(buf);
67 trusty_assert(out_size);
68
69 int num_iovec = 2;
70 struct trusty_ipc_iovec resp_iovecs[2] = {
71 {.base = &resp_hdr, .len = sizeof(resp_hdr)},
72 {.base = buf, .len = buf_size},
73 };
74
75 int rc = trusty_ipc_recv(&hwbcc_chan, resp_iovecs, num_iovec, true);
76 if (rc < 0) {
77 trusty_error("Failure on receiving response: %d\n", rc);
78 return rc;
79 }
80
81 if ((size_t)rc < sizeof(resp_hdr)) {
82 trusty_error("Invalid response size (%d).\n", rc);
83 return TRUSTY_ERR_GENERIC;
84 }
85
86 if (resp_hdr.cmd != (hdr->cmd | HWBCC_CMD_RESP_BIT)) {
87 trusty_error("Unknown response cmd: %x\n", resp_hdr.cmd);
88 return TRUSTY_ERR_GENERIC;
89 }
90
91 if (resp_hdr.status != NO_ERROR) {
92 trusty_error("Status (%d) is not SUCCESS.\n", resp_hdr.status);
93 return TRUSTY_ERR_GENERIC;
94 }
95
96 if (resp_hdr.payload_size != (size_t)rc - sizeof(resp_hdr)) {
97 trusty_error("Invalid payload size: %d.", resp_hdr.payload_size);
98 return TRUSTY_ERR_GENERIC;
99 }
100
101 *out_size = resp_hdr.payload_size;
102 return rc;
103 }
104
read_header_only_response(struct hwbcc_req_hdr * hdr)105 static int read_header_only_response(struct hwbcc_req_hdr* hdr) {
106 struct hwbcc_resp_hdr resp_hdr = {};
107
108 struct trusty_ipc_iovec resp_iovec = {.base = &resp_hdr,
109 .len = sizeof(resp_hdr)};
110
111 int rc = trusty_ipc_recv(&hwbcc_chan, &resp_iovec, 1, true);
112 if (rc < 0) {
113 trusty_error("Failure on receiving response: %d\n", rc);
114 return rc;
115 }
116
117 if ((size_t)rc < sizeof(resp_hdr)) {
118 trusty_error("Invalid response size (%d).\n", rc);
119 return TRUSTY_ERR_GENERIC;
120 }
121
122 if (resp_hdr.cmd != (hdr->cmd | HWBCC_CMD_RESP_BIT)) {
123 trusty_error("Unknown response cmd: %x\n", resp_hdr.cmd);
124 return TRUSTY_ERR_GENERIC;
125 }
126
127 if (resp_hdr.status != NO_ERROR) {
128 trusty_error("Status (%d) is not SUCCESS.\n", resp_hdr.status);
129 return TRUSTY_ERR_GENERIC;
130 }
131
132 return rc;
133 }
134
hwbcc_get_dice_artifacts(uint64_t context,uint8_t * dice_artifacts,size_t dice_artifacts_buf_size,size_t * dice_artifacts_size)135 int hwbcc_get_dice_artifacts(uint64_t context,
136 uint8_t* dice_artifacts,
137 size_t dice_artifacts_buf_size,
138 size_t* dice_artifacts_size) {
139 trusty_assert(dice_artifacts);
140 trusty_assert(dice_artifacts_size);
141
142 struct hwbcc_req_hdr hdr;
143 hdr.cmd = HWBCC_CMD_GET_DICE_ARTIFACTS;
144 hdr.context = context;
145
146 int rc = send_header_only_request(&hdr, sizeof(hdr));
147
148 if (rc < 0) {
149 trusty_error(
150 "In hwbcc_get_dice_artifacts: failed (%d) to send request to HWBCC.",
151 rc);
152 return rc;
153 }
154
155 rc = read_response_with_data(&hdr, dice_artifacts, dice_artifacts_buf_size,
156 dice_artifacts_size);
157
158 if (rc < 0) {
159 trusty_error(
160 "In hwbcc_get_dice_artifacts: failed (%d) to read the response.",
161 rc);
162 return rc;
163 }
164
165 return TRUSTY_ERR_NONE;
166 }
167
hwbcc_ns_deprivilege(void)168 int hwbcc_ns_deprivilege(void) {
169 struct hwbcc_req_hdr hdr = {.cmd = HWBCC_CMD_NS_DEPRIVILEGE};
170 int rc = send_header_only_request(&hdr, sizeof(hdr));
171
172 if (rc < 0) {
173 trusty_error(
174 "In hwbcc_deprivilege: failed (%d) to send request to HWBCC.",
175 rc);
176 return rc;
177 }
178
179 rc = read_header_only_response(&hdr);
180
181 if (rc < 0) {
182 trusty_error("In hwbcc_deprivilege: failed (%d) to read the response.",
183 rc);
184 return rc;
185 }
186
187 return TRUSTY_ERR_NONE;
188 }
189