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 TLOG_TAG "acvp"
18 
19 #include "acvp.h"
20 
21 // NOTE: modulewrapper.h is not guarded against double inclusion and
22 // keymaster_ckdf.h uses it, so we need to include it before keymaster_ckdf.h
23 #include "modulewrapper.h"
24 
25 #include "keymaster_ckdf.h"
26 
27 #include <string>
28 #include <vector>
29 
30 #include <assert.h>
31 #include <interface/acvp/acvp.h>
32 #include <lib/tipc/tipc.h>
33 #include <lib/tipc/tipc_srv.h>
34 #include <lk/err_ptr.h>
35 #include <openssl/digest.h>
36 #include <openssl/hkdf.h>
37 #include <openssl/span.h>
38 #include <sys/auxv.h>
39 #include <sys/mman.h>
40 #include <trusty_ipc.h>
41 #include <trusty_log.h>
42 
43 #define ACVP_PAGE_SIZE getauxval(AT_PAGESZ)
44 
45 // Keep modulewrapper.h and acvp.h in sync
46 static_assert(bssl::acvp::kMaxArgs == ACVP_MAX_NUM_ARGUMENTS);
47 static_assert(bssl::acvp::kMaxNameLength == ACVP_MAX_NAME_LENGTH);
48 
49 static constexpr char kAdditionalConfig[] = R"(,
50 {
51         "algorithm": "KDF",
52         "revision": "1.0",
53         "capabilities": [{
54             "kdfMode": "counter",
55             "macMode": [
56                 "CMAC-AES128",
57                 "CMAC-AES256"
58             ],
59             "supportedLengths": [{
60                 "min": 8,
61                 "max": 4096,
62                 "increment": 8
63             }],
64             "fixedDataOrder": [
65                 "before fixed data"
66             ],
67             "counterLength": [
68                 32
69             ]
70         }]
71 },
72 {
73         "algorithm": "KDA",
74         "mode": "TwoStep",
75         "revision": "Sp800-56Cr2",
76         "capabilities": [{
77             "macSaltMethods": [
78                 "random",
79                 "default"
80             ],
81             "fixedInfoPattern": "uPartyInfo||vPartyInfo",
82             "encoding": [
83                 "concatenation"
84             ],
85             "kdfMode": "feedback",
86             "macMode": [
87                 "HMAC-SHA2-256"
88             ],
89             "supportedLengths": [{
90                 "min": 128,
91                 "max": 1024,
92                 "increment": 64
93             }],
94             "fixedDataOrder": [
95                 "after fixed data"
96             ],
97             "counterLength": [
98                 8
99             ],
100             "requiresEmptyIv": true,
101             "supportsEmptyIv": true
102         }],
103         "l": 1024,
104         "z": [256, 384]
105 }])";
106 
107 static struct tipc_port_acl kAcvpPortAcl = {
108         .flags = IPC_PORT_ALLOW_TA_CONNECT | IPC_PORT_ALLOW_NS_CONNECT,
109         .uuid_num = 0,
110         .uuids = NULL,
111         .extra_data = NULL,
112 };
113 
114 static struct tipc_port kAcvpPort = {
115         .name = ACVP_PORT,
116         .msg_max_size = ACVP_MAX_MESSAGE_LENGTH,
117         .msg_queue_len = 1,
118         .acl = &kAcvpPortAcl,
119         .priv = NULL,
120 };
121 
AlignUpToPage(size_t size)122 static inline size_t AlignUpToPage(size_t size) {
123     return (size + (ACVP_PAGE_SIZE - 1)) & ~(ACVP_PAGE_SIZE - 1);
124 }
125 
126 template <const EVP_MD* HashFunc()>
KAS_HKDF(const bssl::Span<const uint8_t> args[],bssl::acvp::ReplyCallback write_reply)127 static bool KAS_HKDF(const bssl::Span<const uint8_t> args[],
128                      bssl::acvp::ReplyCallback write_reply) {
129     const bssl::Span<const uint8_t> secret = args[0];
130     const bssl::Span<const uint8_t> salt = args[1];
131     const bssl::Span<const uint8_t> info = args[2];
132     const bssl::Span<const uint8_t> out_len_bytes = args[3];
133 
134     uint32_t out_len;
135     if (out_len_bytes.size() != sizeof(out_len)) {
136         return false;
137     }
138     memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
139 
140     std::vector<uint8_t> out(static_cast<size_t>(out_len));
141     int res = HKDF(out.data(), out.size(), HashFunc(), secret.data(),
142                    secret.size(), salt.data(), salt.size(), info.data(),
143                    info.size());
144     if (res != 1) {
145         return false;
146     }
147 
148     return write_reply({out});
149 }
150 
151 class TrustyAcvpTool {
152 public:
TrustyAcvpTool(handle_t chan)153     TrustyAcvpTool(handle_t chan) : chan_(chan), arg_buffer_(NULL) {}
154 
155     // Send a reply back to the acvptool.
156     //
157     // This function is used by the handler functions to write out results and
158     // should be customized by the tool implementation.
159     bool WriteReply(std::vector<bssl::Span<const uint8_t>> spans);
160 
161     bool MapShm(handle_t handle, size_t shm_size);
162 
arg_buffer() const163     const uint8_t* arg_buffer() const {
164         assert(arg_buffer_);
165         return arg_buffer_;
166     }
167 
arg_buffer_size() const168     size_t arg_buffer_size() const { return arg_buffer_size_; }
169 
170     void MessageCleanup();
171 
172     ~TrustyAcvpTool();
173 
174 private:
175     // Communication handle with the Android modulewrapper tool
176     handle_t chan_;
177 
178     // Handle to the shared memory region for arguments
179     handle_t shm_handle_;
180 
181     // Size of arg_buffer_ (must be page-aligned)
182     size_t arg_buffer_size_;
183 
184     // Mapped buffer from shm_handle_
185     uint8_t* arg_buffer_;
186 };
187 
WriteReply(std::vector<bssl::Span<const uint8_t>> spans)188 bool TrustyAcvpTool::WriteReply(std::vector<bssl::Span<const uint8_t>> spans) {
189     if (spans.empty() || spans.size() > bssl::acvp::kMaxArgs) {
190         abort();
191     }
192 
193     struct acvp_resp resp;
194     resp.num_spans = spans.size();
195     uint8_t* cur_buffer = arg_buffer_;
196     for (size_t i = 0; i < spans.size(); i++) {
197         const auto& span = spans[i];
198         resp.lengths[i] = span.size();
199         if (span.empty()) {
200             continue;
201         }
202 
203         assert(span.size() < arg_buffer_size_ &&
204                cur_buffer - arg_buffer_ + span.size() <= arg_buffer_size_);
205         memcpy(cur_buffer, span.data(), span.size());
206         cur_buffer += span.size();
207     }
208 
209     int rc = tipc_send1(chan_, &resp, sizeof(struct acvp_resp));
210     if (rc != sizeof(struct acvp_resp)) {
211         TLOGE("Failed to send ACVP response\n");
212         return false;
213     }
214 
215     return true;
216 }
217 
MapShm(handle_t shm,size_t size)218 bool TrustyAcvpTool::MapShm(handle_t shm, size_t size) {
219     arg_buffer_size_ = AlignUpToPage(size);
220     shm_handle_ = shm;
221     arg_buffer_ = (uint8_t*)mmap(NULL, arg_buffer_size_, PROT_READ | PROT_WRITE,
222                                  0, shm_handle_, 0);
223     if (arg_buffer_ == MAP_FAILED) {
224         return false;
225     }
226 
227     return true;
228 }
229 
MessageCleanup()230 void TrustyAcvpTool::MessageCleanup() {
231     if (arg_buffer_) {
232         int rc = munmap((void*)arg_buffer_, arg_buffer_size_);
233         if (rc != NO_ERROR) {
234             TLOGW("munmap() failed: %d\n", rc);
235         }
236         arg_buffer_ = NULL;
237     }
238 
239     if (shm_handle_ != INVALID_IPC_HANDLE) {
240         close(shm_handle_);
241         shm_handle_ = INVALID_IPC_HANDLE;
242     }
243 }
244 
~TrustyAcvpTool()245 TrustyAcvpTool::~TrustyAcvpTool() {
246     MessageCleanup();
247     if (chan_ != INVALID_IPC_HANDLE) {
248         close(chan_);
249     }
250 }
251 
ParseAcvpMessage(handle_t chan,uint8_t buffer[ACVP_MAX_MESSAGE_LENGTH],struct acvp_req ** request,handle_t * shared_mem)252 static int ParseAcvpMessage(handle_t chan,
253                             uint8_t buffer[ACVP_MAX_MESSAGE_LENGTH],
254                             struct acvp_req** request,
255                             handle_t* shared_mem) {
256     int rc;
257     struct ipc_msg_info msg_info;
258 
259     rc = get_msg(chan, &msg_info);
260     if (rc != NO_ERROR) {
261         TLOGE("failed (%d) to get_msg()\n", rc);
262         return rc;
263     }
264 
265     struct iovec iov = {
266             .iov_base = buffer,
267             .iov_len = ACVP_MAX_MESSAGE_LENGTH,
268     };
269     struct ipc_msg msg = {
270             .num_iov = 1,
271             .iov = &iov,
272             .num_handles = msg_info.num_handles,
273             .handles = shared_mem,
274     };
275 
276     if (msg_info.len < sizeof(struct acvp_req)) {
277         TLOGE("Message is too short: %zd\n", msg_info.len);
278         rc = ERR_BAD_LEN;
279         goto err;
280     }
281 
282     if (msg_info.num_handles != 1) {
283         TLOGE("Expected 1 handle, found %d\n", msg_info.num_handles);
284         rc = ERR_BAD_LEN;
285         goto err;
286     }
287 
288     rc = read_msg(chan, msg_info.id, 0, &msg);
289     if (rc != sizeof(struct acvp_req)) {
290         TLOGE("failed (%d) to read_msg()\n", rc);
291         if (rc >= 0) {
292             rc = ERR_BAD_LEN;
293         }
294         goto err;
295     }
296 
297     rc = NO_ERROR;
298 
299     *request = (struct acvp_req*)buffer;
300 
301 err:
302     put_msg(chan, msg_info.id);
303     return rc;
304 }
305 
AcvpOnConnect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)306 static int AcvpOnConnect(const struct tipc_port* port,
307                          handle_t chan,
308                          const struct uuid* peer,
309                          void** ctx_p) {
310     TrustyAcvpTool* tool = new TrustyAcvpTool(chan);
311     *ctx_p = reinterpret_cast<void*>(tool);
312     return NO_ERROR;
313 }
314 
RewriteConfig(TrustyAcvpTool & tool,const std::vector<bssl::Span<const uint8_t>> & args)315 static bool RewriteConfig(TrustyAcvpTool& tool,
316                           const std::vector<bssl::Span<const uint8_t>>& args) {
317     assert(args.size() == 1);
318     auto config = args[0];
319     const uint8_t* loc = config.cend() - 1;
320     for (; loc >= config.cbegin(); loc--) {
321         if (*loc == '}') {
322             break;
323         }
324     }
325     assert(loc >= config.cbegin() && loc < config.cend());
326     size_t pos = loc - config.cbegin() + 1;
327 
328     std::unique_ptr<uint8_t[]> buf(
329             new (std::nothrow) uint8_t[pos + sizeof(kAdditionalConfig) - 1]);
330     if (!buf) {
331         TLOGE("Could not allocate buffer for config\n");
332         return false;
333     }
334 
335     memcpy(buf.get(), config.cbegin(), pos);
336     memcpy(&buf[pos], kAdditionalConfig, sizeof(kAdditionalConfig) - 1);
337     return tool.WriteReply({bssl::Span<uint8_t>(
338             buf.get(), pos + sizeof(kAdditionalConfig) - 1)});
339 }
340 
341 static constexpr struct {
342     char name[bssl::acvp::kMaxNameLength + 1];
343     uint8_t num_expected_args;
344     bool (*handler)(const bssl::Span<const uint8_t> args[],
345                     bssl::acvp::ReplyCallback write_reply);
346 } kFunctions[] = {
347         {"KDF-counter", 5, KeymasterCKDF},
348         {"HKDF/SHA2-256", 4, KAS_HKDF<EVP_sha256>},
349 };
350 
FindTrustyHandler(bssl::Span<const bssl::Span<const uint8_t>> args)351 static bssl::acvp::Handler FindTrustyHandler(
352         bssl::Span<const bssl::Span<const uint8_t>> args) {
353     const bssl::Span<const uint8_t> algorithm = args[0];
354     for (const auto& func : kFunctions) {
355         if (StringEq(algorithm, func.name)) {
356             if (args.size() - 1 != func.num_expected_args) {
357                 TLOGE("\'%s\' operation received %zu arguments but expected %u.\n",
358                       func.name, args.size() - 1, func.num_expected_args);
359                 return nullptr;
360             }
361 
362             return func.handler;
363         }
364     }
365 
366     const std::string name(reinterpret_cast<const char*>(algorithm.data()),
367                            algorithm.size());
368     TLOGE("Unknown operation: %s\n", name.c_str());
369     return nullptr;
370 }
371 
AcvpOnMessage(const struct tipc_port * port,handle_t chan,void * ctx)372 static int AcvpOnMessage(const struct tipc_port* port,
373                          handle_t chan,
374                          void* ctx) {
375     assert(port == &kAcvpPort);
376     assert(ctx != nullptr);
377 
378     TrustyAcvpTool* tool = reinterpret_cast<TrustyAcvpTool*>(ctx);
379 
380     uint8_t message_buffer[ACVP_MAX_MESSAGE_LENGTH];
381     struct acvp_req* request = nullptr;
382     handle_t shared_mem = INVALID_IPC_HANDLE;
383     int rc = ParseAcvpMessage(chan, message_buffer, &request, &shared_mem);
384     if (rc != NO_ERROR) {
385         TLOGE("Could not parse ACVP message: %d\n", rc);
386         return rc;
387     }
388 
389     if (request->num_args > bssl::acvp::kMaxArgs) {
390         TLOGE("Too many args in ACVP message: %d\n", request->num_args);
391         return ERR_INVALID_ARGS;
392     }
393 
394     if (!tool->MapShm(shared_mem, request->buffer_size)) {
395         TLOGE("Can't map memory\n");
396         if (shared_mem != INVALID_IPC_HANDLE) {
397             close(shared_mem);
398         }
399         return ERR_NO_MEMORY;
400     } else {
401         bssl::Span<const uint8_t> args[bssl::acvp::kMaxArgs];
402         rc = NO_ERROR;
403 
404         uint32_t cur_offset = 0;
405         for (uint32_t i = 0; i < request->num_args; ++i) {
406             uint32_t end;
407             if (__builtin_add_overflow(cur_offset, request->lengths[i], &end) ||
408                 end > tool->arg_buffer_size()) {
409                 rc = ERR_INVALID_ARGS;
410                 goto cleanup;
411             }
412             args[i] = bssl::Span<const uint8_t>(tool->arg_buffer() + cur_offset,
413                                                 request->lengths[i]);
414             cur_offset = end;
415         }
416 
417         auto handler =
418                 bssl::acvp::FindHandler(bssl::Span(args, request->num_args));
419         if (!handler) {
420             handler = FindTrustyHandler(bssl::Span(args, request->num_args));
421         }
422         if (!handler) {
423             const std::string name(
424                     reinterpret_cast<const char*>(args[0].data()),
425                     args[0].size());
426             TLOGE("Unknown operation: %s\n", name.c_str());
427             rc = ERR_NOT_FOUND;
428             goto cleanup;
429         }
430 
431         // We need to intercept getConfig and append our own config to it.
432         bool is_config = StringEq(args[0], "getConfig");
433 
434         bssl::acvp::ReplyCallback callback;
435         if (is_config) {
436             callback = [tool](auto spans) {
437                 return RewriteConfig(*tool, spans);
438             };
439         } else {
440             callback = [tool](auto spans) { return tool->WriteReply(spans); };
441         }
442 
443         if (!handler(&args[1], callback)) {
444             const std::string name(
445                     reinterpret_cast<const char*>(args[0].data()),
446                     args[0].size());
447             TLOGE("\'%s\' operation failed.\n", name.c_str());
448             rc = ERR_GENERIC;
449             goto cleanup;
450         }
451     }
452 
453 cleanup:
454     tool->MessageCleanup();
455 
456     return rc;
457 }
458 
AcvpOnChannelCleanup(void * ctx)459 static void AcvpOnChannelCleanup(void* ctx) {
460     TrustyAcvpTool* tool = reinterpret_cast<TrustyAcvpTool*>(ctx);
461     delete tool;
462 }
463 
464 static struct tipc_srv_ops kAcvpOps = {
465         .on_connect = AcvpOnConnect,
466         .on_message = AcvpOnMessage,
467         .on_channel_cleanup = AcvpOnChannelCleanup,
468 };
469 
main(void)470 int main(void) {
471     struct tipc_hset* hset = tipc_hset_create();
472 
473     if (IS_ERR(hset)) {
474         return PTR_ERR(hset);
475     }
476 
477     int rc = tipc_add_service(hset, &kAcvpPort, 1, 1, &kAcvpOps);
478     if (rc < 0) {
479         return rc;
480     }
481 
482     rc = tipc_run_event_loop(hset);
483     return rc;
484 }
485