2 * Copyright (c) 2016 Google, Inc. All Rights Reserved.
4 * Author: Eric Biggers <ebiggers@google.com>
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.
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.
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
20 #include "platform_defs.h"
27 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
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.
37 /* Policy struct and ioctl numbers */
38 #ifndef FS_IOC_SET_ENCRYPTION_POLICY
39 #define FS_KEY_DESCRIPTOR_SIZE 8
41 struct fscrypt_policy
{
43 __u8 contents_encryption_mode
;
44 __u8 filenames_encryption_mode
;
46 __u8 master_key_descriptor
[FS_KEY_DESCRIPTOR_SIZE
];
47 } __attribute__((packed
));
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 */
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
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 */
70 static cmdinfo_t get_encpolicy_cmd
;
71 static cmdinfo_t set_encpolicy_cmd
;
74 set_encpolicy_help(void)
78 " assign an encryption policy to the currently open file\n"
81 " 'set_encpolicy' - assign policy with default key [0000000000000000]\n"
82 " 'set_encpolicy 0000111122223333' - assign policy with specified key\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"
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"
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"
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"},
109 parse_byte_value(const char *arg
, __u8
*value_ret
)
114 value
= strtol(arg
, &tmp
, 0);
115 if (value
< 0 || value
> 255 || tmp
== arg
|| *tmp
!= '\0')
122 parse_mode(const char *arg
, __u8
*mode_ret
)
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
;
133 return parse_byte_value(arg
, mode_ret
);
142 for (i
= 0; i
< ARRAY_SIZE(available_modes
); i
++)
143 if (mode
== available_modes
[i
].mode
)
144 return available_modes
[i
].name
;
146 sprintf(buf
, "0x%02x", mode
);
151 keydesc2str(__u8 master_key_descriptor
[FS_KEY_DESCRIPTOR_SIZE
])
153 static char buf
[2 * FS_KEY_DESCRIPTOR_SIZE
+ 1];
156 for (i
= 0; i
< FS_KEY_DESCRIPTOR_SIZE
; i
++)
157 sprintf(&buf
[2 * i
], "%02x", master_key_descriptor
[i
]);
163 get_encpolicy_f(int argc
, char **argv
)
165 struct fscrypt_policy policy
;
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
));
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
);
189 set_encpolicy_f(int argc
, char **argv
)
192 struct fscrypt_policy policy
;
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
;
201 while ((c
= getopt(argc
, argv
, "c:n:f:v:")) != EOF
) {
204 if (!parse_mode(optarg
,
205 &policy
.contents_encryption_mode
)) {
206 fprintf(stderr
, "invalid contents encryption "
207 "mode: %s\n", optarg
);
212 if (!parse_mode(optarg
,
213 &policy
.filenames_encryption_mode
)) {
214 fprintf(stderr
, "invalid filenames encryption "
215 "mode: %s\n", optarg
);
220 if (!parse_byte_value(optarg
, &policy
.flags
)) {
221 fprintf(stderr
, "invalid flags: %s\n", optarg
);
226 if (!parse_byte_value(optarg
, &policy
.version
)) {
227 fprintf(stderr
, "invalid policy version: %s\n",
233 return command_usage(&set_encpolicy_cmd
);
240 return command_usage(&set_encpolicy_cmd
);
242 /* Parse key descriptor if specified */
244 const char *keydesc
= argv
[0];
246 unsigned long long x
;
249 if (strlen(keydesc
) != FS_KEY_DESCRIPTOR_SIZE
* 2) {
250 fprintf(stderr
, "invalid key descriptor: %s\n",
255 x
= strtoull(keydesc
, &tmp
, 16);
256 if (tmp
== keydesc
|| *tmp
!= '\0') {
257 fprintf(stderr
, "invalid key descriptor: %s\n",
262 for (i
= 0; i
< FS_KEY_DESCRIPTOR_SIZE
; i
++) {
263 policy
.master_key_descriptor
[i
] = x
>> 56;
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
));
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");
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
;
301 add_command(&get_encpolicy_cmd
);
302 add_command(&set_encpolicy_cmd
);