]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_LIBRBD_CRYPTO_CRYPTO_INTERFACE_H | |
5 | #define CEPH_LIBRBD_CRYPTO_CRYPTO_INTERFACE_H | |
6 | ||
f67539c2 TL |
7 | #include "include/buffer.h" |
8 | #include "include/intarith.h" | |
9 | #include "librbd/io/Types.h" | |
10 | ||
11 | namespace librbd { | |
12 | namespace crypto { | |
13 | ||
1e59de90 | 14 | class CryptoInterface { |
f67539c2 TL |
15 | |
16 | public: | |
1e59de90 TL |
17 | virtual ~CryptoInterface() = default; |
18 | ||
f67539c2 TL |
19 | virtual int encrypt(ceph::bufferlist* data, uint64_t image_offset) = 0; |
20 | virtual int decrypt(ceph::bufferlist* data, uint64_t image_offset) = 0; | |
21 | virtual uint64_t get_block_size() const = 0; | |
22 | virtual uint64_t get_data_offset() const = 0; | |
23 | virtual const unsigned char* get_key() const = 0; | |
24 | virtual int get_key_length() const = 0; | |
25 | ||
26 | inline std::pair<uint64_t, uint64_t> get_pre_and_post_align( | |
27 | uint64_t off, uint64_t len) { | |
28 | if (len == 0) { | |
29 | return std::make_pair(0, 0); | |
30 | } | |
31 | auto block_size = get_block_size(); | |
32 | return std::make_pair(p2phase(off, block_size), | |
33 | p2nphase(off + len, block_size)); | |
34 | } | |
35 | ||
36 | inline std::pair<uint64_t, uint64_t> align(uint64_t off, uint64_t len) { | |
37 | auto aligns = get_pre_and_post_align(off, len); | |
38 | return std::make_pair(off - aligns.first, | |
39 | len + aligns.first + aligns.second); | |
40 | } | |
41 | ||
42 | inline bool is_aligned(uint64_t off, uint64_t len) { | |
43 | auto aligns = get_pre_and_post_align(off, len); | |
44 | return aligns.first == 0 && aligns.second == 0; | |
45 | } | |
46 | ||
47 | inline bool is_aligned(const io::ReadExtents& extents) { | |
48 | for (const auto& extent: extents) { | |
49 | if (!is_aligned(extent.offset, extent.length)) { | |
50 | return false; | |
51 | } | |
52 | } | |
53 | return true; | |
54 | } | |
55 | ||
56 | inline void align_extents(const io::ReadExtents& extents, | |
57 | io::ReadExtents* aligned_extents) { | |
58 | for (const auto& extent: extents) { | |
59 | auto aligned = align(extent.offset, extent.length); | |
60 | aligned_extents->emplace_back(aligned.first, aligned.second); | |
61 | } | |
62 | } | |
63 | ||
64 | inline int decrypt_aligned_extent(io::ReadExtent& extent, | |
65 | uint64_t image_offset) { | |
66 | if (extent.length == 0 || extent.bl.length() == 0) { | |
67 | return 0; | |
68 | } | |
69 | ||
70 | if (extent.extent_map.empty()) { | |
71 | extent.extent_map.emplace_back(extent.offset, extent.bl.length()); | |
72 | } | |
73 | ||
74 | ceph::bufferlist result_bl; | |
75 | io::Extents result_extent_map; | |
76 | ||
77 | ceph::bufferlist curr_block_bl; | |
78 | auto curr_offset = extent.offset; | |
79 | auto curr_block_start_offset = curr_offset; | |
80 | auto curr_block_end_offset = curr_offset; | |
81 | ||
82 | // this will add a final loop iteration for decrypting the last extent | |
83 | extent.extent_map.emplace_back( | |
84 | extent.offset + extent.length + get_block_size(), 0); | |
85 | ||
86 | for (auto [off, len]: extent.extent_map) { | |
87 | auto [aligned_off, aligned_len] = align(off, len); | |
88 | if (aligned_off > curr_block_end_offset) { | |
89 | curr_block_bl.append_zero(curr_block_end_offset - curr_offset); | |
90 | auto curr_block_length = curr_block_bl.length(); | |
91 | if (curr_block_length > 0) { | |
92 | auto r = decrypt( | |
93 | &curr_block_bl, | |
94 | image_offset + curr_block_start_offset - extent.offset); | |
95 | if (r != 0) { | |
96 | return r; | |
97 | } | |
98 | ||
99 | curr_block_bl.splice(0, curr_block_length, &result_bl); | |
100 | result_extent_map.emplace_back( | |
101 | curr_block_start_offset, curr_block_length); | |
102 | } | |
103 | ||
104 | curr_block_start_offset = aligned_off; | |
105 | curr_block_end_offset = aligned_off + aligned_len; | |
106 | curr_offset = aligned_off; | |
107 | } | |
108 | ||
109 | curr_block_bl.append_zero(off - curr_offset); | |
110 | extent.bl.splice(0, len, &curr_block_bl); | |
111 | curr_offset = off + len; | |
112 | curr_block_end_offset = aligned_off + aligned_len; | |
113 | } | |
114 | ||
115 | extent.bl = std::move(result_bl); | |
116 | extent.extent_map = std::move(result_extent_map); | |
117 | ||
118 | return 0; | |
119 | } | |
120 | }; | |
121 | ||
122 | } // namespace crypto | |
123 | } // namespace librbd | |
124 | ||
125 | #endif // CEPH_LIBRBD_CRYPTO_CRYPTO_INTERFACE_H |