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