blob: f4e4635a639d6957a540a16705dd354dc657c8bf [file] [log] [blame] [edit]
# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
# Reference: https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html#user-api
include <uapi/linux/fs.h>
include <uapi/linux/fscrypt.h>
ioctl$FS_IOC_SET_ENCRYPTION_POLICY(fd fd_dir, cmd const[FS_IOC_SET_ENCRYPTION_POLICY], arg ptr[in, fscrypt_policy])
ioctl$FS_IOC_GET_ENCRYPTION_PWSALT(fd fd_dir, cmd const[FS_IOC_GET_ENCRYPTION_PWSALT], arg ptr[out, array[int8, 16]])
ioctl$FS_IOC_GET_ENCRYPTION_POLICY(fd fd, cmd const[FS_IOC_GET_ENCRYPTION_POLICY], arg ptr[out, fscrypt_policy_v1])
ioctl$FS_IOC_GET_ENCRYPTION_POLICY_EX(fd fd, cmd const[FS_IOC_GET_ENCRYPTION_POLICY_EX], arg ptr[inout, fscrypt_get_policy_ex_arg])
ioctl$FS_IOC_ADD_ENCRYPTION_KEY(fd fd_dir, cmd const[FS_IOC_ADD_ENCRYPTION_KEY], arg ptr[inout, fscrypt_add_key_arg])
ioctl$FS_IOC_REMOVE_ENCRYPTION_KEY(fd fd_dir, cmd const[FS_IOC_REMOVE_ENCRYPTION_KEY], arg ptr[inout, fscrypt_remove_key_arg])
ioctl$FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS(fd fd_dir, cmd const[FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS], arg ptr[inout, fscrypt_remove_key_arg])
ioctl$FS_IOC_GET_ENCRYPTION_KEY_STATUS(fd fd_dir, cmd const[FS_IOC_GET_ENCRYPTION_KEY_STATUS], arg ptr[inout, fscrypt_get_key_status_arg])
ioctl$FS_IOC_GET_ENCRYPTION_NONCE(fd fd, cmd const[FS_IOC_GET_ENCRYPTION_NONCE], arg ptr[out, array[int8, 16]])
# Define the types for fscrypt raw keys, key identifiers, and key descriptors.
#
# "Key identifiers" are the new way to identify fscrypt keys. They are 16-byte
# values that must be computed in a specific way from the raw key. The
# FS_IOC_ADD_ENCRYPTION_KEY ioctl will do this computation and return the
# identifier to userspace, as a side effect of adding a key. But it's unclear
# that syzkaller can understand this flow yet (as arrays can't be resources), so
# we also define some sample keys with precomputed identifiers to use.
#
# "Key descriptors" are the old way to identify fscrypt keys. They are 8-byte
# values arbitrarily assigned by userspace.
fscrypt_raw_key [
auto array[int8[16:64]]
# 64-byte keys (usable with aes256, aes128, adiantum)
a stringnoz[`0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40`]
b stringnoz["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa11111111111111111111111111111111"]
# 32-byte key (usable with aes128, adiantum)
c stringnoz["abcdefghijklmnopqrstuvwxyz0123456"]
# 16-byte key (usable with aes128 only)
d stringnoz["abcdefghijklmnop"]
] [varlen]
fscrypt_key_identifier [
auto array[int8, FSCRYPT_KEY_IDENTIFIER_SIZE]
# These 16-byte values are computed from the raw keys listed above.
a stringnoz[`69b2f6edeee720cce0577937eb8a6751`]
b stringnoz[`912ae510a458723a839a9fad701538ac`]
c stringnoz[`1c2d6754b6cc7daacb599875d7faf9bb`]
d stringnoz[`7eb80af3f24ef086726a4cea3a154ce0`]
]
fscrypt_key_descriptor [
auto array[int8, FSCRYPT_KEY_DESCRIPTOR_SIZE]
# These are arbitrary 8-byte values.
desc1 stringnoz[`0000111122223333`]
desc2 stringnoz[`e355a76a11a1be18`]
desc3 stringnoz[`e8dab99234bb312e`]
desc4 stringnoz[`85baa174f0cb1142`]
]
# fscrypt_key_descriptor translated into a hex string
fscrypt_key_descriptor_hex [
auto array[flags[hex_chars, int8], 16]
desc1 stringnoz["0000111122223333"]
desc2 stringnoz["e355a76a11a1be18"]
desc3 stringnoz["e8dab99234bb312e"]
desc4 stringnoz["85baa174f0cb1142"]
]
# Below are the data structures needed to put keys for fscrypt_policy_v1 in the
# regular Linux keyrings via the add_key() syscall. Note that this part of the
# API is deprecated in favor of FS_IOC_ADD_ENCRYPTION_KEY and fscrypt_policy_v2.
fscrypt_v1_key_description {
prefix stringnoz["fscrypt:"]
descriptor fscrypt_key_descriptor_hex
nil const[0, int8]
}
fscrypt_v1_key_payload {
mode const[0, int32]
# This really should be fscrypt_raw_key, but that has the varlen attribute so it
# doesn't work in this struct.
raw array[int8, 64]
size int32[16:64]
}
# Structs for the ioctls that get and set encryption policies
fscrypt_policy_v1 {
version const[0, int8]
modes fscrypt_policy_modes
flags flags[fscrypt_policy_flags, int8]
master_key_descriptor fscrypt_key_descriptor
}
fscrypt_policy_v2 {
version const[2, int8]
modes fscrypt_policy_modes
flags flags[fscrypt_policy_flags, int8]
reserved array[const[0, int8], 4]
master_key_identifier fscrypt_key_identifier
}
fscrypt_policy [
v1 fscrypt_policy_v1
v2 fscrypt_policy_v2
] [varlen]
fscrypt_policy_modes [
aes256 fscrypt_policy_mode_t[FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS]
aes128 fscrypt_policy_mode_t[FSCRYPT_MODE_AES_128_CBC, FSCRYPT_MODE_AES_128_CTS]
adiantum fscrypt_policy_mode_t[FSCRYPT_MODE_ADIANTUM, FSCRYPT_MODE_ADIANTUM]
]
type fscrypt_policy_mode_t[CONTENTS, FILENAMES] {
contents_encryption_mode const[CONTENTS, int8]
filenames_encryption_mode const[FILENAMES, int8]
}
fscrypt_policy_flags = FSCRYPT_POLICY_FLAGS_PAD_4, FSCRYPT_POLICY_FLAGS_PAD_8, FSCRYPT_POLICY_FLAGS_PAD_16, FSCRYPT_POLICY_FLAGS_PAD_32, FSCRYPT_POLICY_FLAG_DIRECT_KEY, FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64, FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32
fscrypt_get_policy_ex_arg {
policy_size len[policy, int64] (in)
policy array[const[0, int8]] (out)
}
# Structs for the ioctls that manage keys in the filesystem-level keyring
fscrypt_key_specifier [
desc fscrypt_key_specifier__by_descriptor
id fscrypt_key_specifier__by_identifier
]
fscrypt_key_specifier__by_descriptor {
type const[FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR, int32]
reserved const[0, int32]
descriptor fscrypt_key_descriptor
reserved2 array[const[0, int8], 24]
}
fscrypt_key_specifier__by_identifier {
type const[FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, int32]
reserved const[0, int32]
identifier fscrypt_key_identifier
reserved2 array[const[0, int8], 16]
}
# Usually, fscrypt_key_specifier is entirely an input. But in
# FS_IOC_ADD_ENCRYPTION_KEY, if 'fscrypt_add_key_arg::key_spec.type' is set to
# FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, then
# 'fscrypt_add_key_arg::key_spec.identifier' is an output field. The version of
# fscrypt_key_specifier below has per-field directions set to represent this.
fscrypt_key_specifier__for_add_key [
desc fscrypt_key_specifier__by_descriptor
id fscrypt_key_specifier__by_identifier_for_add_key
]
fscrypt_key_specifier__by_identifier_for_add_key {
type const[FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, int32] (in)
reserved const[0, int32] (in)
identifier fscrypt_key_identifier (out)
reserved2 array[const[0, int8], 16] (in)
}
fscrypt_key_specifier_type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR, FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER
fscrypt_provisioning_key_payload {
type flags[fscrypt_key_specifier_type, int32]
reserved const[0, int32]
raw fscrypt_raw_key
}
fscrypt_add_key_arg {
key_spec fscrypt_key_specifier__for_add_key
raw_size bytesize[raw, int32] (in)
key_id fscrypt_provisioning_key[opt] (in)
reserved array[const[0, int32], 8] (in)
raw fscrypt_raw_key (in)
}
fscrypt_remove_key_arg {
key_spec fscrypt_key_specifier (in)
removal_status_flags int32 (out)
reserved array[const[0, int32], 5] (in)
}
fscrypt_get_key_status_arg {
key_spec fscrypt_key_specifier (in)
reserved array[const[0, int32], 6] (in)
status int32 (out)
status_flags int32 (out)
user_count int32 (out)
out_reserved array[const[0, int32], 13] (out)
}