1207753Smm// Copyright 2018 The Fuchsia Authors. All rights reserved.
2207753Smm// Use of this source code is governed by a BSD-style license that can be
3207753Smm// found in the LICENSE file.
4207753Smm
5207753Smm#pragma once
6207753Smm
7207753Smm#include <stdint.h>
8207753Smm#include <threads.h>
9207753Smm
10207753Smm#include <crypto/cipher.h>
11207753Smm#include <lib/zx/port.h>
12207753Smm#include <zircon/syscalls/port.h>
13207753Smm#include <zircon/types.h>
14207753Smm#include <zxcrypt/volume.h>
15207753Smm
16207753Smm#include "extra.h"
17207753Smm
18207753Smmnamespace zxcrypt {
19207753Smm
20207753Smmclass Device;
21207753Smm
22207753Smm// |zxcrypt::Worker| represents a thread performing cryptographic transformations on block I/O data.
23207753Smm// Since these operations may have significant and asymmetric costs between encrypting and
24207753Smm// 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.
26class Worker final {
27public:
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
46private:
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|.
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