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