1 /*
2  * Copyright 2024 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 <endian.h>
18 #include <trusty/secretkeeper.h>
19 #include <trusty/trusty_ipc.h>
20 #include <trusty/util.h>
21 
22 static struct trusty_ipc_chan secretkeeper_chan;
23 static bool initialized;
24 
secretkeeper_tipc_init(struct trusty_ipc_dev * dev)25 int secretkeeper_tipc_init(struct trusty_ipc_dev* dev) {
26     trusty_assert(dev);
27     trusty_assert(!initialized);
28     trusty_ipc_chan_init(&secretkeeper_chan, dev);
29 
30     trusty_debug(
31             "In secretkeeper_tipc_init: connecting to secretkeeper bootloader service.\n");
32     int rc = trusty_ipc_connect(&secretkeeper_chan, SECRETKEEPER_BL_PORT,
33                                 true /*wait*/);
34     if (rc < 0) {
35         trusty_error(
36                 "In secretkeeper_tipc_init:: failed (%d) to connect to '%s'.\n",
37                 rc, SECRETKEEPER_BL_PORT);
38         return rc;
39     }
40     initialized = true;
41     return TRUSTY_ERR_NONE;
42 }
43 
secretkeeper_tipc_shutdown(void)44 void secretkeeper_tipc_shutdown(void) {
45     if (!initialized) {
46         return;
47     }
48     trusty_ipc_close(&secretkeeper_chan);
49     initialized = false;
50 }
51 
send_header_only_request(struct secretkeeper_req_hdr * hdr,size_t hdr_size)52 static int send_header_only_request(struct secretkeeper_req_hdr* hdr,
53                                     size_t hdr_size) {
54     int num_iovec = 1;
55     struct trusty_ipc_iovec req_iov = {.base = hdr, .len = hdr_size};
56     return trusty_ipc_send(&secretkeeper_chan, &req_iov, num_iovec, true);
57 }
58 
read_response_with_data(struct secretkeeper_req_hdr * hdr,uint8_t * buf,size_t buf_size,size_t * out_size)59 static int read_response_with_data(struct secretkeeper_req_hdr* hdr,
60                                    uint8_t* buf,
61                                    size_t buf_size,
62                                    size_t* out_size) {
63     struct secretkeeper_resp_hdr resp_hdr = {};
64 
65     trusty_assert(buf);
66     trusty_assert(out_size);
67 
68     int num_iovec = 2;
69     struct trusty_ipc_iovec resp_iovecs[2] = {
70             {.base = &resp_hdr, .len = sizeof(resp_hdr)},
71             {.base = buf, .len = buf_size},
72     };
73 
74     int rc = trusty_ipc_recv(&secretkeeper_chan, resp_iovecs, num_iovec, true);
75     if (rc < 0) {
76         trusty_error("Secretkeeper: Failure on receiving response: %d\n", rc);
77         return rc;
78     }
79 
80     size_t bytes = rc;
81     if (bytes < sizeof(resp_hdr)) {
82         trusty_error("Secretkeeper: Invalid response size (%d).\n", rc);
83         return TRUSTY_ERR_GENERIC;
84     }
85 
86     if (resp_hdr.cmd != (hdr->cmd | htonl(SECRETKEEPER_RESPONSE_MARKER))) {
87         trusty_error("Secretkeeper: Unknown response cmd: %x\n",
88                      ntohl(resp_hdr.cmd));
89         return TRUSTY_ERR_GENERIC;
90     }
91 
92     if (resp_hdr.error_code != 0) {
93         trusty_error("Secretkeeper: Error code (%d) is not zero.\n",
94                      ntohl(resp_hdr.error_code));
95         return TRUSTY_ERR_GENERIC;
96     }
97 
98     *out_size = bytes - sizeof(resp_hdr);
99     return rc;
100 }
101 
secretkeeper_get_identity(size_t identity_buf_size,uint8_t identity_buf[],size_t * identity_size)102 int secretkeeper_get_identity(size_t identity_buf_size,
103                               uint8_t identity_buf[],
104                               size_t* identity_size) {
105     trusty_assert(dice_artifacts);
106     trusty_assert(dice_artifacts_size);
107 
108     struct secretkeeper_req_hdr hdr;
109     hdr.cmd = htonl(SECRETKEEPER_CMD_GET_IDENTITY);
110 
111     int rc = send_header_only_request(&hdr, sizeof(hdr));
112 
113     if (rc < 0) {
114         trusty_error(
115                 "In secretkeeper_get_identity: failed (%d) to send request to Secretkeeper.",
116                 rc);
117         return rc;
118     }
119 
120     rc = read_response_with_data(&hdr, identity_buf, identity_buf_size,
121                                  identity_size);
122 
123     if (rc < 0) {
124         trusty_error(
125                 "In secretkeeper_get_identity: failed (%d) to read the response.",
126                 rc);
127         return rc;
128     }
129 
130     return TRUSTY_ERR_NONE;
131 }
132