]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/encrypt.c
xfs_io: support the new getfsmap ioctl
[thirdparty/xfsprogs-dev.git] / io / encrypt.c
1 /*
2 * Copyright (c) 2016 Google, Inc. All Rights Reserved.
3 *
4 * Author: Eric Biggers <ebiggers@google.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "platform_defs.h"
21 #include "command.h"
22 #include "init.h"
23 #include "path.h"
24 #include "io.h"
25
26 #ifndef ARRAY_SIZE
27 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
28 #endif
29
30 /*
31 * We may have to declare the fscrypt ioctls ourselves because someone may be
32 * compiling xfsprogs with old kernel headers. And since some old versions of
33 * <linux/fs.h> declared the policy struct and ioctl numbers but not the flags
34 * and modes, our declarations must be split into two conditional blocks.
35 */
36
37 /* Policy struct and ioctl numbers */
38 #ifndef FS_IOC_SET_ENCRYPTION_POLICY
39 #define FS_KEY_DESCRIPTOR_SIZE 8
40
41 struct fscrypt_policy {
42 __u8 version;
43 __u8 contents_encryption_mode;
44 __u8 filenames_encryption_mode;
45 __u8 flags;
46 __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
47 } __attribute__((packed));
48
49 #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
50 #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
51 #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
52 #endif /* FS_IOC_SET_ENCRYPTION_POLICY */
53
54 /* Policy flags and encryption modes */
55 #ifndef FS_ENCRYPTION_MODE_AES_256_XTS
56 #define FS_POLICY_FLAGS_PAD_4 0x00
57 #define FS_POLICY_FLAGS_PAD_8 0x01
58 #define FS_POLICY_FLAGS_PAD_16 0x02
59 #define FS_POLICY_FLAGS_PAD_32 0x03
60 #define FS_POLICY_FLAGS_PAD_MASK 0x03
61 #define FS_POLICY_FLAGS_VALID 0x03
62
63 #define FS_ENCRYPTION_MODE_INVALID 0
64 #define FS_ENCRYPTION_MODE_AES_256_XTS 1
65 #define FS_ENCRYPTION_MODE_AES_256_GCM 2
66 #define FS_ENCRYPTION_MODE_AES_256_CBC 3
67 #define FS_ENCRYPTION_MODE_AES_256_CTS 4
68 #endif /* FS_ENCRYPTION_MODE_AES_256_XTS */
69
70 static cmdinfo_t get_encpolicy_cmd;
71 static cmdinfo_t set_encpolicy_cmd;
72
73 static void
74 set_encpolicy_help(void)
75 {
76 printf(_(
77 "\n"
78 " assign an encryption policy to the currently open file\n"
79 "\n"
80 " Examples:\n"
81 " 'set_encpolicy' - assign policy with default key [0000000000000000]\n"
82 " 'set_encpolicy 0000111122223333' - assign policy with specified key\n"
83 "\n"
84 " -c MODE -- contents encryption mode\n"
85 " -n MODE -- filenames encryption mode\n"
86 " -f FLAGS -- policy flags\n"
87 " -v VERSION -- version of policy structure\n"
88 "\n"
89 " MODE can be numeric or one of the following predefined values:\n"
90 " AES-256-XTS, AES-256-CTS, AES-256-GCM, AES-256-CBC\n"
91 " FLAGS and VERSION must be numeric.\n"
92 "\n"
93 " Note that it's only possible to set an encryption policy on an empty\n"
94 " directory. It's then inherited by new files and subdirectories.\n"
95 "\n"));
96 }
97
98 static const struct {
99 __u8 mode;
100 const char *name;
101 } available_modes[] = {
102 {FS_ENCRYPTION_MODE_AES_256_XTS, "AES-256-XTS"},
103 {FS_ENCRYPTION_MODE_AES_256_CTS, "AES-256-CTS"},
104 {FS_ENCRYPTION_MODE_AES_256_GCM, "AES-256-GCM"},
105 {FS_ENCRYPTION_MODE_AES_256_CBC, "AES-256-CBC"},
106 };
107
108 static bool
109 parse_byte_value(const char *arg, __u8 *value_ret)
110 {
111 long value;
112 char *tmp;
113
114 value = strtol(arg, &tmp, 0);
115 if (value < 0 || value > 255 || tmp == arg || *tmp != '\0')
116 return false;
117 *value_ret = value;
118 return true;
119 }
120
121 static bool
122 parse_mode(const char *arg, __u8 *mode_ret)
123 {
124 int i;
125
126 for (i = 0; i < ARRAY_SIZE(available_modes); i++) {
127 if (strcmp(arg, available_modes[i].name) == 0) {
128 *mode_ret = available_modes[i].mode;
129 return true;
130 }
131 }
132
133 return parse_byte_value(arg, mode_ret);
134 }
135
136 static const char *
137 mode2str(__u8 mode)
138 {
139 static char buf[32];
140 int i;
141
142 for (i = 0; i < ARRAY_SIZE(available_modes); i++)
143 if (mode == available_modes[i].mode)
144 return available_modes[i].name;
145
146 sprintf(buf, "0x%02x", mode);
147 return buf;
148 }
149
150 static const char *
151 keydesc2str(__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE])
152 {
153 static char buf[2 * FS_KEY_DESCRIPTOR_SIZE + 1];
154 int i;
155
156 for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
157 sprintf(&buf[2 * i], "%02x", master_key_descriptor[i]);
158
159 return buf;
160 }
161
162 static int
163 get_encpolicy_f(int argc, char **argv)
164 {
165 struct fscrypt_policy policy;
166
167 if (ioctl(file->fd, FS_IOC_GET_ENCRYPTION_POLICY, &policy) < 0) {
168 fprintf(stderr, "%s: failed to get encryption policy: %s\n",
169 file->name, strerror(errno));
170 exitcode = 1;
171 return 0;
172 }
173
174 printf("Encryption policy for %s:\n", file->name);
175 printf("\tPolicy version: %u\n", policy.version);
176 printf("\tMaster key descriptor: %s\n",
177 keydesc2str(policy.master_key_descriptor));
178 printf("\tContents encryption mode: %u (%s)\n",
179 policy.contents_encryption_mode,
180 mode2str(policy.contents_encryption_mode));
181 printf("\tFilenames encryption mode: %u (%s)\n",
182 policy.filenames_encryption_mode,
183 mode2str(policy.filenames_encryption_mode));
184 printf("\tFlags: 0x%02x\n", policy.flags);
185 return 0;
186 }
187
188 static int
189 set_encpolicy_f(int argc, char **argv)
190 {
191 int c;
192 struct fscrypt_policy policy;
193
194 /* Initialize the policy structure with default values */
195 memset(&policy, 0, sizeof(policy));
196 policy.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
197 policy.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
198 policy.flags = FS_POLICY_FLAGS_PAD_16;
199
200 /* Parse options */
201 while ((c = getopt(argc, argv, "c:n:f:v:")) != EOF) {
202 switch (c) {
203 case 'c':
204 if (!parse_mode(optarg,
205 &policy.contents_encryption_mode)) {
206 fprintf(stderr, "invalid contents encryption "
207 "mode: %s\n", optarg);
208 return 0;
209 }
210 break;
211 case 'n':
212 if (!parse_mode(optarg,
213 &policy.filenames_encryption_mode)) {
214 fprintf(stderr, "invalid filenames encryption "
215 "mode: %s\n", optarg);
216 return 0;
217 }
218 break;
219 case 'f':
220 if (!parse_byte_value(optarg, &policy.flags)) {
221 fprintf(stderr, "invalid flags: %s\n", optarg);
222 return 0;
223 }
224 break;
225 case 'v':
226 if (!parse_byte_value(optarg, &policy.version)) {
227 fprintf(stderr, "invalid policy version: %s\n",
228 optarg);
229 return 0;
230 }
231 break;
232 default:
233 return command_usage(&set_encpolicy_cmd);
234 }
235 }
236 argc -= optind;
237 argv += optind;
238
239 if (argc > 1)
240 return command_usage(&set_encpolicy_cmd);
241
242 /* Parse key descriptor if specified */
243 if (argc > 0) {
244 const char *keydesc = argv[0];
245 char *tmp;
246 unsigned long long x;
247 int i;
248
249 if (strlen(keydesc) != FS_KEY_DESCRIPTOR_SIZE * 2) {
250 fprintf(stderr, "invalid key descriptor: %s\n",
251 keydesc);
252 return 0;
253 }
254
255 x = strtoull(keydesc, &tmp, 16);
256 if (tmp == keydesc || *tmp != '\0') {
257 fprintf(stderr, "invalid key descriptor: %s\n",
258 keydesc);
259 return 0;
260 }
261
262 for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
263 policy.master_key_descriptor[i] = x >> 56;
264 x <<= 8;
265 }
266 }
267
268 /* Set the encryption policy */
269 if (ioctl(file->fd, FS_IOC_SET_ENCRYPTION_POLICY, &policy) < 0) {
270 fprintf(stderr, "%s: failed to set encryption policy: %s\n",
271 file->name, strerror(errno));
272 exitcode = 1;
273 return 0;
274 }
275
276 return 0;
277 }
278
279 void
280 encrypt_init(void)
281 {
282 get_encpolicy_cmd.name = "get_encpolicy";
283 get_encpolicy_cmd.cfunc = get_encpolicy_f;
284 get_encpolicy_cmd.argmin = 0;
285 get_encpolicy_cmd.argmax = 0;
286 get_encpolicy_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
287 get_encpolicy_cmd.oneline =
288 _("display the encryption policy of the current file");
289
290 set_encpolicy_cmd.name = "set_encpolicy";
291 set_encpolicy_cmd.cfunc = set_encpolicy_f;
292 set_encpolicy_cmd.args =
293 _("[-c mode] [-n mode] [-f flags] [-v version] [keydesc]");
294 set_encpolicy_cmd.argmin = 0;
295 set_encpolicy_cmd.argmax = -1;
296 set_encpolicy_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
297 set_encpolicy_cmd.oneline =
298 _("assign an encryption policy to the current file");
299 set_encpolicy_cmd.help = set_encpolicy_help;
300
301 add_command(&get_encpolicy_cmd);
302 add_command(&set_encpolicy_cmd);
303 }