1 // Copyright 2017 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 <stddef.h>
8 #include <stdint.h>
9 
10 #include <crypto/aead.h>
11 #include <crypto/bytes.h>
12 #include <crypto/cipher.h>
13 #include <crypto/digest.h>
14 #include <crypto/secret.h>
15 #include <ddk/device.h>
16 #include <fbl/macros.h>
17 #include <fbl/unique_fd.h>
18 #include <fbl/unique_ptr.h>
19 #include <lib/zx/time.h>
20 #include <zircon/device/block.h>
21 #include <zircon/types.h>
22 
23 // |zxcrypt::Volume| manages the interactions of both driver and library code with the metadata
24 // used to format and operate zxcrypt devices.  The superblock is saved multiple times on disk to
25 // provide redundancy.
26 //
27 // It manages three types of key material:
28 //  - Root: Provided by the consumers of this class.
29 //  - Data: Randomly generated at volume creation and used to encrypt and decrypt the volumes data.
30 //  - Wrap: Derived from the root keys and used to encrypt and decrypt the data key material.
31 namespace zxcrypt {
32 
33 // Forward declaration of unit test framework.
34 namespace testing{
35 class TestDevice;
36 }
37 
38 // TODO(aarongreen): ZX-1130 workaround: Until we have a means to pass the root key on binding, we
39 // simply use a null key of a fixed length. Remove this constant when ZX-1130 is resolved.
40 const size_t kZx1130KeyLen = 32;
41 
42 using key_slot_t = zx_off_t;
43 
44 class Volume final {
45 public:
46     // The supported version, named by the algorithms they use.  New version should increment the
47     // version number and update the default version.  Zero indicates an error state.
48     enum Version : uint32_t {
49         kUninitialized = 0,
50         kAES256_XTS_SHA256,
51     };
52 
53     // The default version, used when sealing a new volume.
54     static const Version kDefaultVersion;
55 
56     // The amount of data that can "in-flight" to the underlying block device before the zxcrypt
57     // driver begins queuing transactions
58     static const uint32_t kBufferSize;
59 
60     explicit Volume(fbl::unique_fd&& fd);
61     explicit Volume(zx_device_t* dev);
62     ~Volume();
63     DISALLOW_COPY_ASSIGN_AND_MOVE(Volume);
64 
65     // Returns space reserved for metadata and keys
reserved_blocks()66     size_t reserved_blocks() const { return reserved_blocks_; }
reserved_slices()67     size_t reserved_slices() const { return reserved_slices_; }
num_slots()68     size_t num_slots() const { return num_key_slots_; }
69 
70     // Returns a new volume object corresponding to the block device given by |fd| and populated
71     // with the block and FVM information.
72     static zx_status_t Init(fbl::unique_fd fd, fbl::unique_ptr<Volume>* out = nullptr);
73 
74     // Creates a new zxcrypt volume associated with the given file descriptor, |fd| and returns it
75     // via |out|, if provided.  This will format the block device as zxcrypt using the given |key|,
76     // which will be associated with key slot 0. This method takes ownership of |fd|.
77     static zx_status_t Create(fbl::unique_fd fd, const crypto::Secret& key,
78                               fbl::unique_ptr<Volume>* out = nullptr);
79 
80     // Opens a zxcrypt volume on the block device described by |fd| using the |key| corresponding to
81     // given key |slot|.  The |fd| parameter means this method can be used from libzxcrypt. This
82     // method takes ownership of |fd|.
83     static zx_status_t Unlock(fbl::unique_fd fd, const crypto::Secret& key, key_slot_t slot,
84                               fbl::unique_ptr<Volume>* out);
85 
86     // Unlocks a zxcrypt volume on the block device described by |dev| using the |key| corresponding
87     // to given key |slot|.  The |dev| parameter means this method can be used from the driver.
88     static zx_status_t Unlock(zx_device_t* dev, const crypto::Secret& key, key_slot_t slot,
89                               fbl::unique_ptr<Volume>* out);
90 
91     // Opens a zxcrypt volume on the block device described by |fd| using the |key| corresponding to
92     // given key |slot|.
93     zx_status_t Unlock(const crypto::Secret& key, key_slot_t slot = 0);
94 
95     // Opens the zxcrypt volume and returns a file descriptor to it via |out|, or fails if the
96     // volume isn't available within |timeout|.
97     zx_status_t Open(const zx::duration& timeout, fbl::unique_fd* out);
98 
99     // Uses the data key material to initialize |cipher| for the given |direction|.  This method
100     // must only be called from the zxcrypt driver.
101     zx_status_t Bind(crypto::Cipher::Direction direction, crypto::Cipher* cipher) const;
102 
103     // Adds a given |key| to the given key |slot|.  This key can then be used to |Open| the
104     // zxcrypt device.  This method can only be called if the volume belongs to libzxcrypt.
105     zx_status_t Enroll(const crypto::Secret& key, key_slot_t slot);
106 
107     // Removes the root key in the given key |slot|.  This key can no longer be used to |Open| the
108     // zxcrypt device.  This method can only be called if the volume belongs to libzxcrypt.
109     zx_status_t Revoke(key_slot_t slot);
110 
111     // Removes ALL keys, rendering any data in the zxcrypt device inaccessible.  It is an error to
112     // call any method except the destructor on this instance after this methods returns.
113     zx_status_t Shred();
114 
115 private:
116     friend class testing::TestDevice;
117 
118     ////////////////
119     // Configuration methods
120 
121     // Retrieves the block and FVM information and adjusts it.
122     zx_status_t Init();
123 
124     // Maps the volume version to crypto algorithms.
125     zx_status_t Configure(Version version);
126 
127     // Returns via |out| the offset in bytes for the given key |slot|.  Returns an error if the
128     // volume hasn't been initialized, or if |slot| is out of range.
129     zx_status_t GetSlotOffset(key_slot_t slot, zx_off_t* out) const;
130 
131     // Derives intermediate keys for the given key |slot| from the given |key|.
132     zx_status_t DeriveSlotKeys(const crypto::Secret& key, key_slot_t slot);
133 
134     // Resets all fields in this object to initial values
135     void Reset();
136 
137     ////////////////
138     // Block methods
139 
140     // Resets the superblock offset to the first location (block 0).
141     zx_status_t Begin();
142 
143     // Advances the superblock offset to the next volume location.  Returns ZX_ERR_STOP if no more
144     // offsets available; ZX_ERR_NEXT otherwise.
145     zx_status_t Next();
146 
147     // Creates a new volume, with a new instance GUID and data key and IV, and seals it with the
148     // given |key|
149     zx_status_t CreateBlock();
150 
151     // Writes |block| out to each of the superblock locations.
152     zx_status_t CommitBlock();
153 
154     // Encrypts the current data key and IV to the given |slot| using the given |key|.
155     zx_status_t SealBlock(const crypto::Secret& key, key_slot_t slot);
156 
157     // Reads the block and parses and checks various fields before attempting to open it with the
158     // given |key| corresponding to the given |slot|.
159     zx_status_t UnsealBlock(const crypto::Secret& key, key_slot_t slot);
160 
161     ////////////////
162     // Device methods
163 
164     // Sends an I/O control message to the underlying device and reads the response.
165     zx_status_t Ioctl(int op, const void* in, size_t in_len, void* out, size_t out_len);
166 
167     // Reads a block from the current offset on the underlying device.
168     zx_status_t Read();
169 
170     // Writes a block to the current offset on the underlying device.
171     zx_status_t Write();
172 
173     ////////////////
174     // Fields
175 
176     // The underlying block device as accessed via DDK or FDIO.
177     zx_device_t* dev_;
178     fbl::unique_fd fd_;
179 
180     // The space reserved for metadata.
181     uint64_t reserved_blocks_;
182     uint64_t reserved_slices_;
183 
184     // Buffer holding the current block being examined, and its offset on the underlying device.
185     crypto::Bytes block_;
186     zx_off_t offset_;
187 
188     // The instance GUID for this device.
189     crypto::Bytes guid_;
190     // A copy of the entire header, used as AAD for the AEAD.
191     crypto::Bytes header_;
192 
193     // The algorithm, lengths, and buffers for the key-wrapping AEAD.
194     crypto::AEAD::Algorithm aead_;
195     crypto::Secret wrap_key_;
196     crypto::Bytes wrap_iv_;
197 
198     // The algorithm for data processing Cipher and length of wrapped key material.
199     crypto::Cipher::Algorithm cipher_;
200     crypto::Secret data_key_;
201     crypto::Bytes data_iv_;
202     size_t slot_len_;
203     size_t num_key_slots_;
204 
205     // The digest used by the HKDF.
206     crypto::digest::Algorithm digest_;
207 };
208 
209 } // namespace zxcrypt
210