]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/encrypt.c
xfs_io: support the new getfsmap ioctl
[thirdparty/xfsprogs-dev.git] / io / encrypt.c
CommitLineData
0cf66b0f
EB
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"
3fcab549 23#include "path.h"
0cf66b0f
EB
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
41struct 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
70static cmdinfo_t get_encpolicy_cmd;
71static cmdinfo_t set_encpolicy_cmd;
72
73static void
74set_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
98static 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
108static bool
109parse_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
121static bool
122parse_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
136static const char *
137mode2str(__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
150static const char *
151keydesc2str(__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
162static int
163get_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
188static int
189set_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
279void
280encrypt_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}