1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stdint.h>
8 #include <threads.h>
9 
10 #include <crypto/cipher.h>
11 #include <lib/zx/port.h>
12 #include <zircon/syscalls/port.h>
13 #include <zircon/types.h>
14 #include <zxcrypt/volume.h>
15 
16 #include "extra.h"
17 
18 namespace zxcrypt {
19 
20 class Device;
21 
22 // |zxcrypt::Worker| represents a thread performing cryptographic transformations on block I/O data.
23 // Since these operations may have significant and asymmetric costs between encrypting and
24 // decrypting, they are performed asynchronously on separate threads.  The |zxcrypt::Device| may
25 // spin up multiple workers pulling from a shared queues to optimize the throughput.
26 class Worker final {
27 public:
28     Worker();
29     ~Worker();
30 
31     // Opcodes for requests that can be sent to workers.
32     static constexpr uint64_t kBlockRequest = 0x1;
33     static constexpr uint64_t kStopRequest = 0x2;
34 
35     // Configure the given |packet| to be an |op| request, with an optional |arg|.
36     static void MakeRequest(zx_port_packet_t* packet, uint64_t op, void* arg = nullptr);
37 
38     // Starts the worker, which will service requests sent from the given |device| on the given
39     // |port|.  Cryptographic operations will use the key material from the given |volume|.
40     zx_status_t Start(Device* device, const Volume& volume, zx::port&& port);
41 
42     // Asks the worker to stop.  This call blocks until the worker has finished processing the
43     // currently queued operations and exits.
44     zx_status_t Stop();
45 
46 private:
47     DISALLOW_COPY_ASSIGN_AND_MOVE(Worker);
48 
49     // Loop thread.  Reads an I/O request from the |port_| and dispatches it between |EncryptWrite|
50     // and |DecryptRead|.
WorkerRun(void * arg)51     static int WorkerRun(void* arg) { return static_cast<Worker*>(arg)->Run(); }
52     zx_status_t Run();
53 
54     // Copies the plaintext data to be written to the write buffer location given in |block|'s extra
55     // information, and encrypts it before sending it to the parent device.
56     zx_status_t EncryptWrite(block_op_t* block);
57 
58     // Maps the ciphertext data in |block|, and decrypts it in place before completing the block op.
59     zx_status_t DecryptRead(block_op_t* block);
60 
61     // The cipher objects used to perform cryptographic.  See notes on "random access" in
62     // crypto/cipher.h.
63     crypto::Cipher encrypt_;
64     crypto::Cipher decrypt_;
65 
66     // The device associated with this worker.
67     Device* device_;
68 
69     // The port to wait for I/O request on, as given by the device.
70     zx::port port_;
71 
72     // The executing thread for this worker
73     thrd_t thrd_;
74 };
75 
76 } // namespace zxcrypt
77