1 /*
2  * Copyright 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 #define LOG_TAG "TrustyAcvpModulewrapper"
18 
19 #include <BufferAllocator/BufferAllocator.h>
20 #include <android-base/file.h>
21 #include <android-base/result.h>
22 #include <android-base/unique_fd.h>
23 #include <errno.h>
24 #include <iostream>
25 #include <log/log.h>
26 #include <modulewrapper.h>
27 #include <openssl/span.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/mman.h>
32 #include <trusty/tipc.h>
33 #include <unistd.h>
34 #include <algorithm>
35 
36 #include "acvp_ipc.h"
37 
38 constexpr const char kTrustyDeviceName[] = "/dev/trusty-ipc-dev0";
39 
40 using android::base::ErrnoError;
41 using android::base::Error;
42 using android::base::Result;
43 using android::base::unique_fd;
44 using android::base::WriteFully;
45 
46 
47 namespace {
48 
49 class ModuleWrapper {
50   private:
51     static const char* kAcvpPort_;
52     static const char* kTrustyDeviceName_;
53 
54   public:
55     ModuleWrapper();
56     ~ModuleWrapper();
57 
58     Result<void> SendMessage(bssl::Span<const bssl::Span<const uint8_t>>);
59 
60     Result<void> ForwardResponse();
61 
62   private:
63     // Connection to the Trusty ACVP service
64     int tipc_fd_ = -1;
65 
66     // Shared memory DMA buf
67     unique_fd dmabuf_fd_;
68 
69     // Size of shared memory mapping
70     size_t shm_size_ = 0;
71 
72     // Shared memory mapping
73     uint8_t* shm_buffer_ = nullptr;
74 };
75 
76 }  // namespace
77 
78 const char* ModuleWrapper::kAcvpPort_ = ACVP_PORT;
79 const char* ModuleWrapper::kTrustyDeviceName_ = kTrustyDeviceName;
80 
ModuleWrapper()81 ModuleWrapper::ModuleWrapper() {
82     tipc_fd_ = tipc_connect(kTrustyDeviceName_, kAcvpPort_);
83     if (tipc_fd_ < 0) {
84         fprintf(stderr, "Failed to connect to Trusty ACVP test app: %s\n", strerror(-tipc_fd_));
85     }
86 }
87 
~ModuleWrapper()88 ModuleWrapper::~ModuleWrapper() {
89     if (tipc_fd_ >= 0) {
90         tipc_close(tipc_fd_);
91     }
92 
93     if (shm_buffer_) {
94         munmap(shm_buffer_, shm_size_);
95     }
96 }
97 
SendMessage(bssl::Span<const bssl::Span<const uint8_t>> args)98 Result<void> ModuleWrapper::SendMessage(bssl::Span<const bssl::Span<const uint8_t>> args) {
99     assert(args.size() < ACVP_MAX_NUM_ARGUMENTS);
100     assert(args[0].size() < ACVP_MAX_NAME_LENGTH);
101 
102     struct acvp_req request;
103     request.num_args = args.size();
104 
105     int total_args_size = 0;
106     for (auto arg : args) {
107         total_args_size += arg.size();
108     }
109 
110     shm_size_ = std::max(ACVP_MIN_SHARED_MEMORY, total_args_size);
111     request.buffer_size = shm_size_;
112 
113     struct iovec iov = {
114             .iov_base = &request,
115             .iov_len = sizeof(struct acvp_req),
116     };
117 
118     BufferAllocator alloc;
119     dmabuf_fd_.reset(alloc.Alloc(kDmabufSystemHeapName, shm_size_));
120     if (!dmabuf_fd_.ok()) {
121         return ErrnoError() << "Error creating dmabuf";
122     }
123 
124     shm_buffer_ = (uint8_t*)mmap(0, shm_size_, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd_, 0);
125     if (shm_buffer_ == MAP_FAILED) {
126         return ErrnoError() << "Failed to map shared memory dmabuf";
127     }
128 
129     size_t cur_offset = 0;
130     for (int i = 0; i < args.size(); ++i) {
131         request.lengths[i] = args[i].size();
132         memcpy(shm_buffer_ + cur_offset, args[i].data(), args[i].size());
133         cur_offset += args[i].size();
134     }
135 
136     struct trusty_shm shm = {
137             .fd = dmabuf_fd_.get(),
138             .transfer = TRUSTY_SHARE,
139     };
140 
141     int rc = tipc_send(tipc_fd_, &iov, 1, &shm, 1);
142     if (rc != sizeof(struct acvp_req)) {
143         return ErrnoError() << "Failed to send request to Trusty ACVP service";
144     }
145 
146     return {};
147 }
148 
ForwardResponse()149 Result<void> ModuleWrapper::ForwardResponse() {
150     struct acvp_resp resp;
151     int bytes_read = read(tipc_fd_, &resp, sizeof(struct acvp_resp));
152     if (bytes_read < 0) {
153         return ErrnoError() << "Failed to read response from Trusty ACVP service";
154     }
155 
156     if (bytes_read != sizeof(struct acvp_resp)) {
157         return Error() << "Trusty ACVP response overflowed expected size";
158     }
159 
160     size_t total_args_size = 0;
161     for (size_t i = 0; i < resp.num_spans; i++) {
162         total_args_size += resp.lengths[i];
163     }
164 
165     iovec iovs[2];
166     iovs[0].iov_base = &resp;
167     iovs[0].iov_len = sizeof(uint32_t) * (1 + resp.num_spans);
168 
169     iovs[1].iov_base = shm_buffer_;
170     iovs[1].iov_len = total_args_size;
171 
172     size_t iov_done = 0;
173     while (iov_done < 2) {
174         ssize_t r;
175         do {
176             r = writev(STDOUT_FILENO, &iovs[iov_done], 2 - iov_done);
177         } while (r == -1 && errno == EINTR);
178 
179         if (r <= 0) {
180             return Error() << "Failed to write ACVP response to standard out";
181         }
182 
183         size_t written = r;
184         for (size_t i = iov_done; i < 2 && written > 0; i++) {
185             iovec& iov = iovs[i];
186 
187             size_t done = written;
188             if (done > iov.iov_len) {
189                 done = iov.iov_len;
190             }
191 
192             iov.iov_base = reinterpret_cast<uint8_t*>(iov.iov_base) + done;
193             iov.iov_len -= done;
194             written -= done;
195 
196             if (iov.iov_len == 0) {
197                 iov_done++;
198             }
199         }
200 
201         assert(written == 0);
202     }
203 
204     return {};
205 }
206 
EqString(bssl::Span<const uint8_t> cmd,const char * str)207 static bool EqString(bssl::Span<const uint8_t> cmd, const char *str) {
208     return cmd.size() == strlen(str) &&
209            memcmp(str, cmd.data(), cmd.size()) == 0;
210 }
211 
main()212 int main() {
213     for (;;) {
214         auto buffer = bssl::acvp::RequestBuffer::New();
215         auto args = bssl::acvp::ParseArgsFromFd(STDIN_FILENO, buffer.get());
216         if (args.empty()) {
217             ALOGE("Could not parse arguments\n");
218             return EXIT_FAILURE;
219         }
220 
221         if (EqString(args[0], "flush")) {
222             if (!bssl::acvp::FlushBuffer(STDOUT_FILENO)) {
223                 ALOGE("Could not flush the buffer to stdout\n");
224                 return EXIT_FAILURE;
225             }
226         } else {
227             ModuleWrapper wrapper;
228             auto res = wrapper.SendMessage(args);
229             if (!res.ok()) {
230                 std::cerr << res.error() << std::endl;
231                 return EXIT_FAILURE;
232             }
233 
234             res = wrapper.ForwardResponse();
235             if (!res.ok()) {
236                 std::cerr << res.error() << std::endl;
237                 return EXIT_FAILURE;
238             }
239         }
240     }
241 
242     return EXIT_SUCCESS;
243 };
244