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