@@ -15,42 +15,126 @@
#endif
/*
- * We may have to declare the fscrypt ioctls ourselves because someone may be
- * compiling xfsprogs with old kernel headers. And since some old versions of
- * <linux/fs.h> declared the policy struct and ioctl numbers but not the flags
- * and modes, our declarations must be split into two conditional blocks.
+ * Declare the fscrypt ioctls if needed, since someone may be compiling xfsprogs
+ * with old kernel headers. But <linux/fs.h> has already been included, so be
+ * careful not to declare things twice.
*/
-/* Policy struct and ioctl numbers */
+/* first batch of ioctls (Linux headers v4.6+) */
#ifndef FS_IOC_SET_ENCRYPTION_POLICY
-#define FS_KEY_DESCRIPTOR_SIZE 8
+#define fscrypt_policy fscrypt_policy_v1
+#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
+#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
+#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
+#endif
+
+/*
+ * Second batch of ioctls (Linux headers v5.4+), plus some renamings from FS_ to
+ * FSCRYPT_. We don't bother defining the old names here.
+ */
+#ifndef FS_IOC_GET_ENCRYPTION_POLICY_EX
+
+#define FSCRYPT_POLICY_FLAGS_PAD_4 0x00
+#define FSCRYPT_POLICY_FLAGS_PAD_8 0x01
+#define FSCRYPT_POLICY_FLAGS_PAD_16 0x02
+#define FSCRYPT_POLICY_FLAGS_PAD_32 0x03
+#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03
+#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
+
+#define FSCRYPT_MODE_AES_256_XTS 1
+#define FSCRYPT_MODE_AES_256_CTS 4
+#define FSCRYPT_MODE_AES_128_CBC 5
+#define FSCRYPT_MODE_AES_128_CTS 6
+#define FSCRYPT_MODE_ADIANTUM 9
+
+/*
+ * In the headers for Linux v4.6 through v5.3, 'struct fscrypt_policy_v1' is
+ * already defined under its old name, 'struct fscrypt_policy'. But it's fine
+ * to define it under its new name too.
+ *
+ * Note: "v1" policies really are version "0" in the API.
+ */
+#define FSCRYPT_POLICY_V1 0
+#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8
+struct fscrypt_policy_v1 {
+ __u8 version;
+ __u8 contents_encryption_mode;
+ __u8 filenames_encryption_mode;
+ __u8 flags;
+ __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
+};
-struct fscrypt_policy {
+#define FSCRYPT_POLICY_V2 2
+#define FSCRYPT_KEY_IDENTIFIER_SIZE 16
+struct fscrypt_policy_v2 {
__u8 version;
__u8 contents_encryption_mode;
__u8 filenames_encryption_mode;
__u8 flags;
- __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
-} __attribute__((packed));
-
-#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
-#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
-#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
-#endif /* FS_IOC_SET_ENCRYPTION_POLICY */
-
-/* Policy flags and encryption modes */
-#ifndef FS_ENCRYPTION_MODE_AES_256_XTS
-#define FS_POLICY_FLAGS_PAD_4 0x00
-#define FS_POLICY_FLAGS_PAD_8 0x01
-#define FS_POLICY_FLAGS_PAD_16 0x02
-#define FS_POLICY_FLAGS_PAD_32 0x03
-#define FS_POLICY_FLAGS_PAD_MASK 0x03
-#define FS_POLICY_FLAGS_VALID 0x03
-
-#define FS_ENCRYPTION_MODE_INVALID 0
-#define FS_ENCRYPTION_MODE_AES_256_XTS 1
-#define FS_ENCRYPTION_MODE_AES_256_CTS 4
-#endif /* FS_ENCRYPTION_MODE_AES_256_XTS */
+ __u8 __reserved[4];
+ __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
+};
+
+#define FSCRYPT_MAX_KEY_SIZE 64
+
+#define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */
+struct fscrypt_get_policy_ex_arg {
+ __u64 policy_size; /* input/output */
+ union {
+ __u8 version;
+ struct fscrypt_policy_v1 v1;
+ struct fscrypt_policy_v2 v2;
+ } policy; /* output */
+};
+
+#define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1
+#define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2
+struct fscrypt_key_specifier {
+ __u32 type; /* one of FSCRYPT_KEY_SPEC_TYPE_* */
+ __u32 __reserved;
+ union {
+ __u8 __reserved[32]; /* reserve some extra space */
+ __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
+ __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
+ } u;
+};
+
+#define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg)
+struct fscrypt_add_key_arg {
+ struct fscrypt_key_specifier key_spec;
+ __u32 raw_size;
+ __u32 __reserved[9];
+ __u8 raw[];
+};
+
+#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
+#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
+struct fscrypt_remove_key_arg {
+ struct fscrypt_key_specifier key_spec;
+#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY 0x00000001
+#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS 0x00000002
+ __u32 removal_status_flags; /* output */
+ __u32 __reserved[5];
+};
+
+#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
+struct fscrypt_get_key_status_arg {
+ /* input */
+ struct fscrypt_key_specifier key_spec;
+ __u32 __reserved[6];
+
+ /* output */
+#define FSCRYPT_KEY_STATUS_ABSENT 1
+#define FSCRYPT_KEY_STATUS_PRESENT 2
+#define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3
+ __u32 status;
+#define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001
+ __u32 status_flags;
+ __u32 user_count;
+ __u32 __out_reserved[13];
+};
+
+#endif /* !FS_IOC_GET_ENCRYPTION_POLICY_EX */
static cmdinfo_t get_encpolicy_cmd;
static cmdinfo_t set_encpolicy_cmd;
@@ -84,8 +168,8 @@ static const struct {
__u8 mode;
const char *name;
} available_modes[] = {
- {FS_ENCRYPTION_MODE_AES_256_XTS, "AES-256-XTS"},
- {FS_ENCRYPTION_MODE_AES_256_CTS, "AES-256-CTS"},
+ {FSCRYPT_MODE_AES_256_XTS, "AES-256-XTS"},
+ {FSCRYPT_MODE_AES_256_CTS, "AES-256-CTS"},
};
static bool
@@ -131,12 +215,12 @@ mode2str(__u8 mode)
}
static const char *
-keydesc2str(__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE])
+keydesc2str(__u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE])
{
- static char buf[2 * FS_KEY_DESCRIPTOR_SIZE + 1];
+ static char buf[2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1];
int i;
- for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
+ for (i = 0; i < FSCRYPT_KEY_DESCRIPTOR_SIZE; i++)
sprintf(&buf[2 * i], "%02x", master_key_descriptor[i]);
return buf;
@@ -176,9 +260,9 @@ set_encpolicy_f(int argc, char **argv)
/* Initialize the policy structure with default values */
memset(&policy, 0, sizeof(policy));
- policy.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
- policy.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
- policy.flags = FS_POLICY_FLAGS_PAD_16;
+ policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+ policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+ policy.flags = FSCRYPT_POLICY_FLAGS_PAD_16;
/* Parse options */
while ((c = getopt(argc, argv, "c:n:f:v:")) != EOF) {
@@ -229,7 +313,7 @@ set_encpolicy_f(int argc, char **argv)
unsigned long long x;
int i;
- if (strlen(keydesc) != FS_KEY_DESCRIPTOR_SIZE * 2) {
+ if (strlen(keydesc) != FSCRYPT_KEY_DESCRIPTOR_SIZE * 2) {
fprintf(stderr, "invalid key descriptor: %s\n",
keydesc);
return 0;
@@ -242,7 +326,7 @@ set_encpolicy_f(int argc, char **argv)
return 0;
}
- for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
+ for (i = 0; i < FSCRYPT_KEY_DESCRIPTOR_SIZE; i++) {
policy.master_key_descriptor[i] = x >> 56;
x <<= 8;
}