| # 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) |
| } |